Whitespace

This commit is contained in:
Ryan Jarvis
2020-05-01 11:28:50 -07:00
parent 9ebbb439cb
commit 81a37df50e
31 changed files with 1575 additions and 1600 deletions

View File

@@ -54,7 +54,6 @@ class Actions(object):
def move_browser_selection_page_up(self): def move_browser_selection_page_up(self):
self.display.browser_menu.navigate_menu_page_up() self.display.browser_menu.navigate_menu_page_up()
def enter_on_browser_selection(self): def enter_on_browser_selection(self):
self.display.browser_menu.enter_on_browser_selection() self.display.browser_menu.enter_on_browser_selection()
@@ -70,7 +69,6 @@ class Actions(object):
def move_settings_selection_page_up(self): def move_settings_selection_page_up(self):
self.display.settings_menu.navigate_menu_page_up() self.display.settings_menu.navigate_menu_page_up()
def enter_on_settings_selection(self): def enter_on_settings_selection(self):
is_setting, setting = self.display.settings_menu.enter_on_setting_selection() is_setting, setting = self.display.settings_menu.enter_on_setting_selection()
if is_setting: if is_setting:
@@ -92,7 +90,6 @@ class Actions(object):
def move_shaders_selection_page_up(self): def move_shaders_selection_page_up(self):
self.shaders.shaders_menu.navigate_menu_page_up() self.shaders.shaders_menu.navigate_menu_page_up()
def enter_on_shaders_selection(self): def enter_on_shaders_selection(self):
##want to select shader if its not selected, and want to enter 'param' mode if it already is ##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() 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): if self.data.update_next_slot_number(slot, is_current=True):
self.video_driver.reload_current_player() self.video_driver.reload_current_player()
def load_slot_0_into_next_player(self): def load_slot_0_into_next_player(self):
self._load_this_slot_into_next_player(0) self._load_this_slot_into_next_player(0)
@@ -186,7 +181,7 @@ class Actions(object):
display_mode = display_mode.upper() display_mode = display_mode.upper()
display_modes = self.data.get_display_modes_list(with_nav_mode=True) display_modes = self.data.get_display_modes_list(with_nav_mode=True)
for i,dm in enumerate(display_modes): for i, dm in enumerate(display_modes):
if display_mode in dm: if display_mode in dm:
self.data.display_mode = display_modes[i][0] self.data.display_mode = display_modes[i][0]
self.data.control_mode = display_modes[i][1] self.data.control_mode = display_modes[i][1]
@@ -207,7 +202,6 @@ class Actions(object):
self.data.display_mode = display_modes[next_mode_index][0] self.data.display_mode = display_modes[next_mode_index][0]
self.data.control_mode = display_modes[next_mode_index][1] self.data.control_mode = display_modes[next_mode_index][1]
def toggle_action_on_player(self): def toggle_action_on_player(self):
play = 'play' in self.data.settings['sampler']['ON_ACTION']['value'] play = 'play' in self.data.settings['sampler']['ON_ACTION']['value']
show = 'show' in self.data.settings['sampler']['ON_ACTION']['value'] show = 'show' in self.data.settings['sampler']['ON_ACTION']['value']
@@ -230,18 +224,16 @@ class Actions(object):
def increase_seek_time(self): def increase_seek_time(self):
options = self.data.settings['sampler']['SEEK_TIME']['options'] 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] 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.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') 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): def decrease_seek_time(self):
options = self.data.settings['sampler']['SEEK_TIME']['options'] 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] 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.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') 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): def seek_forward_on_player(self):
self.video_driver.current_player.seek(self.data.settings['sampler']['SEEK_TIME']['value']) self.video_driver.current_player.seek(self.data.settings['sampler']['SEEK_TIME']['value'])
@@ -270,18 +262,18 @@ class Actions(object):
new_rate = self.video_driver.current_player.change_rate(1) new_rate = self.video_driver.current_player.change_rate(1)
current_bank, current_slot = self.data.split_bankslot_number(self.video_driver.current_player.bankslot_number) current_bank, current_slot = self.data.split_bankslot_number(self.video_driver.current_player.bankslot_number)
self.data.update_slot_rate_to_this(current_slot, new_rate) self.data.update_slot_rate_to_this(current_slot, new_rate)
#self._load_this_slot_into_next_player(current_slot) # self._load_this_slot_into_next_player(current_slot)
def decrease_speed(self): def decrease_speed(self):
print("increasing speed !") print("increasing speed !")
new_rate = self.video_driver.current_player.change_rate(-1) new_rate = self.video_driver.current_player.change_rate(-1)
current_bank, current_slot = self.data.split_bankslot_number(self.video_driver.current_player.bankslot_number) current_bank, current_slot = self.data.split_bankslot_number(self.video_driver.current_player.bankslot_number)
self.data.update_slot_rate_to_this(current_slot, new_rate) self.data.update_slot_rate_to_this(current_slot, new_rate)
#self._load_this_slot_into_next_player(current_slot) # self._load_this_slot_into_next_player(current_slot)
def set_playing_sample_start_to_current_duration(self): def set_playing_sample_start_to_current_duration(self):
current_bank, current_slot = self.data.split_bankslot_number(self.video_driver.current_player.bankslot_number) current_bank, current_slot = self.data.split_bankslot_number(self.video_driver.current_player.bankslot_number)
current_position = round(self.video_driver.current_player.get_position(),3) current_position = round(self.video_driver.current_player.get_position(), 3)
self.data.update_slot_start_to_this_time(current_slot, current_position) self.data.update_slot_start_to_this_time(current_slot, current_position)
self._load_this_slot_into_next_player(current_slot) self._load_this_slot_into_next_player(current_slot)
@@ -292,7 +284,7 @@ class Actions(object):
def set_playing_sample_end_to_current_duration(self): def set_playing_sample_end_to_current_duration(self):
current_bank, current_slot = self.data.split_bankslot_number(self.video_driver.current_player.bankslot_number) current_bank, current_slot = self.data.split_bankslot_number(self.video_driver.current_player.bankslot_number)
current_position = round(self.video_driver.current_player.get_position(),0) current_position = round(self.video_driver.current_player.get_position(), 0)
self.data.update_slot_end_to_this_time(current_slot, current_position) self.data.update_slot_end_to_this_time(current_slot, current_position)
self._load_this_slot_into_next_player(current_slot) self._load_this_slot_into_next_player(current_slot)
@@ -305,13 +297,12 @@ class Actions(object):
is_previewing = self.capture.is_previewing is_previewing = self.capture.is_previewing
if is_previewing: if is_previewing:
self.capture.stop_preview() self.capture.stop_preview()
#if self.video_driver.current_player.status == 'PAUSED': # if self.video_driver.current_player.status == 'PAUSED':
#self.video_driver.current_player.toggle_pause() # self.video_driver.current_player.toggle_pause()
else: else:
is_successful = self.capture.start_preview() is_successful = self.capture.start_preview()
#if is_successful and self.video_driver.current_player.status != 'PAUSED': # if is_successful and self.video_driver.current_player.status != 'PAUSED':
#self.video_driver.current_player.toggle_pause() # self.video_driver.current_player.toggle_pause()
def toggle_capture_recording(self): def toggle_capture_recording(self):
is_recording = self.capture.is_recording is_recording = self.capture.is_recording
@@ -480,7 +471,6 @@ class Actions(object):
self.data.detour_settings['current_detour'] = number self.data.detour_settings['current_detour'] = number
self.video_driver.osc_client.send_message("/detour/switch_to_detour_number", number) self.video_driver.osc_client.send_message("/detour/switch_to_detour_number", number)
def set_detour_delay_mode(self, state): def set_detour_delay_mode(self, state):
self.video_driver.osc_client.send_message("/detour/set_delay_mode", state == 'enabled') self.video_driver.osc_client.send_message("/detour/set_delay_mode", state == 'enabled')
self.data.update_conjur_delay_mode(state == 'enabled') self.data.update_conjur_delay_mode(state == 'enabled')
@@ -513,19 +503,19 @@ class Actions(object):
self.set_detour_mix_continuous(1) self.set_detour_mix_continuous(1)
def set_the_camera_colour_u_continuous(self, amount): def set_the_camera_colour_u_continuous(self, amount):
self.capture.set_colour(amount*255, None) self.capture.set_colour(amount * 255, None)
def set_the_camera_colour_v_continuous(self, amount): def set_the_camera_colour_v_continuous(self, amount):
self.capture.set_colour(None, amount*255) self.capture.set_colour(None, amount * 255)
def set_the_camera_alpha_continuous(self, amount): def set_the_camera_alpha_continuous(self, amount):
self.capture.set_alpha(amount*255) self.capture.set_alpha(amount * 255)
def set_the_current_video_alpha_continuous(self, amount): def set_the_current_video_alpha_continuous(self, amount):
self.video_driver.current_player.set_alpha_value(amount*255) self.video_driver.current_player.set_alpha_value(amount * 255)
def set_the_next_video_alpha_continuous(self, amount): def set_the_next_video_alpha_continuous(self, amount):
self.video_driver.next_player.set_alpha_value(amount*255) self.video_driver.next_player.set_alpha_value(amount * 255)
def set_the_shader_param_0_layer_offset_0_continuous(self, amount): def set_the_shader_param_0_layer_offset_0_continuous(self, amount):
self.shaders.set_param_to_amount(0, amount, layer_offset=0) self.shaders.set_param_to_amount(0, amount, layer_offset=0)
@@ -583,8 +573,8 @@ class Actions(object):
self.data.update_setting_value('shader', 'STROBE_AMOUNT', scaled_amount) self.data.update_setting_value('shader', 'STROBE_AMOUNT', scaled_amount)
def get_midi_status(self): def get_midi_status(self):
device_name = 'none' if not hasattr(self.data,'midi_device_name') else self.data.midi_device_name device_name = 'none' if not hasattr(self.data, 'midi_device_name') else self.data.midi_device_name
self.message_handler.set_message('INFO', ("midi status is {} to %s"%(device_name)).format(self.data.midi_status)) self.message_handler.set_message('INFO', ("midi status is {} to %s" % (device_name)).format(self.data.midi_status))
def cycle_midi_port_index(self): def cycle_midi_port_index(self):
self.data.midi_port_index = self.data.midi_port_index + 1 self.data.midi_port_index = self.data.midi_port_index + 1
@@ -634,19 +624,18 @@ class Actions(object):
self.change_hdmi_settings('CEA 4 HDMI') self.change_hdmi_settings('CEA 4 HDMI')
def check_dev_mode(self): def check_dev_mode(self):
#### check if in dev mode:(ie not using the lcd screen) #### check if in dev mode:(ie not using the lcd screen)
with open('/boot/config.txt', 'r') as config: with open('/boot/config.txt', 'r') as config:
if '##no_waveshare_overlay' in config.read(): if '##no_waveshare_overlay' in config.read():
self.data.update_setting_value('system','DEV_MODE_RESET', 'on') self.data.update_setting_value('system', 'DEV_MODE_RESET', 'on')
else: else:
self.data.update_setting_value('system','DEV_MODE_RESET', 'off') self.data.update_setting_value('system', 'DEV_MODE_RESET', 'off')
def check_if_should_start_openframeworks(self): def check_if_should_start_openframeworks(self):
if self.data.settings['video']['VIDEOPLAYER_BACKEND']['value'] != 'omxplayer': if self.data.settings['video']['VIDEOPLAYER_BACKEND']['value'] != 'omxplayer':
with open("conjur.log","w+") as out: with open("conjur.log", "w+") as out:
self.openframeworks_process = subprocess.Popen([self.data.PATH_TO_OPENFRAMEWORKS +'apps/myApps/c_o_n_j_u_r/bin/c_o_n_j_u_r'], stdout=out) self.openframeworks_process = subprocess.Popen([self.data.PATH_TO_OPENFRAMEWORKS + 'apps/myApps/c_o_n_j_u_r/bin/c_o_n_j_u_r'], stdout=out)
print('conjur pid is {}'.format(self.openframeworks_process.pid)) print('conjur pid is {}'.format(self.openframeworks_process.pid))
def exit_openframeworks(self): def exit_openframeworks(self):
@@ -682,14 +671,13 @@ class Actions(object):
progressive = 'p' progressive = 'p'
if output == 'composite': if output == 'composite':
subprocess.call(['tvservice --sdtvon="{} {} {}"'.format(mode, aspect, progressive)],shell=True) subprocess.call(['tvservice --sdtvon="{} {} {}"'.format(mode, aspect, progressive)], shell=True)
self.refresh_frame_buffer_and_restart_openframeworks() self.refresh_frame_buffer_and_restart_openframeworks()
self.persist_composite_setting(mode, progressive, aspect) self.persist_composite_setting(mode, progressive, aspect)
def _refresh_frame_buffer(self): def _refresh_frame_buffer(self):
self.data.open_omxplayer_for_reset() self.data.open_omxplayer_for_reset()
subprocess.run(["fbset -depth 16; fbset -depth 32; xrefresh -display :0" ], shell=True) subprocess.run(["fbset -depth 16; fbset -depth 32; xrefresh -display :0"], shell=True)
def persist_composite_setting(self, mode, progressive, aspect): def persist_composite_setting(self, mode, progressive, aspect):
sdtv_mode = '' sdtv_mode = ''
@@ -714,7 +702,7 @@ class Actions(object):
self.update_config_settings(sdtv_mode, sdtv_aspect) self.update_config_settings(sdtv_mode, sdtv_aspect)
def update_config_settings(self, sdtv_mode, sdtv_aspect): def update_config_settings(self, sdtv_mode, sdtv_aspect):
self.run_script('set_composite_mode',sdtv_mode, sdtv_aspect) self.run_script('set_composite_mode', sdtv_mode, sdtv_aspect)
def switch_dev_mode(self, state): def switch_dev_mode(self, state):
if state == 'on': if state == 'on':
@@ -734,7 +722,6 @@ class Actions(object):
else: else:
self.message_handler.set_message('INFO', 'failed to switch display') self.message_handler.set_message('INFO', 'failed to switch display')
def switch_display_to_lcd(self): def switch_display_to_lcd(self):
with open('/boot/config.txt', 'r') as config: with open('/boot/config.txt', 'r') as config:
with open('/usr/share/X11/xorg.conf.d/99-fbturbo.conf') as framebuffer_conf: with open('/usr/share/X11/xorg.conf.d/99-fbturbo.conf') as framebuffer_conf:
@@ -745,8 +732,8 @@ class Actions(object):
self.message_handler.set_message('INFO', 'failed to switch display') self.message_handler.set_message('INFO', 'failed to switch display')
def run_script(self, script_name, first_argument='', second_argument=''): def run_script(self, script_name, first_argument='', second_argument=''):
print('first arg is {} , second is {}'.format(first_argument,second_argument)) print('first arg is {} , second is {}'.format(first_argument, second_argument))
subprocess.call(['/home/pi/r_e_c_u_r/dotfiles/{}.sh'.format(script_name),first_argument, second_argument ]) subprocess.call(['/home/pi/r_e_c_u_r/dotfiles/{}.sh'.format(script_name), first_argument, second_argument])
def toggle_x_autorepeat(self): def toggle_x_autorepeat(self):
if self.data.auto_repeat_on: if self.data.auto_repeat_on:
@@ -756,13 +743,12 @@ class Actions(object):
subprocess.call(['xset', 'r', 'on']) subprocess.call(['xset', 'r', 'on'])
self.data.auto_repeat_on = True self.data.auto_repeat_on = True
def quit_the_program(self): def quit_the_program(self):
self.data._update_json(self.data.SETTINGS_JSON, self.data.settings) self.data._update_json(self.data.SETTINGS_JSON, self.data.settings)
self.data.plugins.quit_plugins() self.data.plugins.quit_plugins()
self.video_driver.exit_all_players() self.video_driver.exit_all_players()
self.exit_openframeworks() self.exit_openframeworks()
self.exit_osc_server('','') self.exit_osc_server('', '')
self.create_client_and_shutdown_osc_server() self.create_client_and_shutdown_osc_server()
self.stop_serial_port_process() self.stop_serial_port_process()
self.stop_openframeworks_process() self.stop_openframeworks_process()
@@ -772,7 +758,7 @@ class Actions(object):
def restart_the_program(self): def restart_the_program(self):
self.quit_the_program() self.quit_the_program()
os.execv('/usr/bin/python3', [sys.argv[0],'/home/pi/r_e_c_u_r/r_e_c_u_r.py']) os.execv('/usr/bin/python3', [sys.argv[0], '/home/pi/r_e_c_u_r/r_e_c_u_r.py'])
def set_shader_param_mode(self): def set_shader_param_mode(self):
self.data.control_mode = 'SHADER_PARAM' self.data.control_mode = 'SHADER_PARAM'
@@ -786,21 +772,21 @@ class Actions(object):
self.shaders.decrease_this_param(self.data.settings['shader']['SHADER_PARAM']['value']) self.shaders.decrease_this_param(self.data.settings['shader']['SHADER_PARAM']['value'])
def increase_param_focus(self): def increase_param_focus(self):
self.shaders.focused_param = (self.shaders.focused_param + 1)%self.shaders.selected_shader_list[self.data.shader_layer]['param_number'] self.shaders.focused_param = (self.shaders.focused_param + 1) % self.shaders.selected_shader_list[self.data.shader_layer]['param_number']
def decrease_param_focus(self): def decrease_param_focus(self):
self.shaders.focused_param = (self.shaders.focused_param - 1)%self.shaders.selected_shader_list[self.data.shader_layer]['param_number'] self.shaders.focused_param = (self.shaders.focused_param - 1) % self.shaders.selected_shader_list[self.data.shader_layer]['param_number']
def increase_shader_param(self): def increase_shader_param(self):
options = self.data.settings['shader']['SHADER_PARAM']['options'] options = self.data.settings['shader']['SHADER_PARAM']['options']
current_index = [index for index, item in enumerate(options) if item == self.data.settings['shader']['SHADER_PARAM']['value'] ][0] current_index = [index for index, item in enumerate(options) if item == self.data.settings['shader']['SHADER_PARAM']['value']][0]
self.data.update_setting_value('shader', 'SHADER_PARAM', options[(current_index + 1) % len(options) ]) self.data.update_setting_value('shader', 'SHADER_PARAM', options[(current_index + 1) % len(options)])
self.message_handler.set_message('INFO', 'The Param amount is now ' + str(self.data.settings['shader']['SHADER_PARAM']['value'])) self.message_handler.set_message('INFO', 'The Param amount is now ' + str(self.data.settings['shader']['SHADER_PARAM']['value']))
def decrease_shader_param(self): def decrease_shader_param(self):
options = self.data.settings['shader']['SHADER_PARAM']['options'] options = self.data.settings['shader']['SHADER_PARAM']['options']
current_index = [index for index, item in enumerate(options) if item == self.data.settings['shader']['SHADER_PARAM']['value'] ][0] current_index = [index for index, item in enumerate(options) if item == self.data.settings['shader']['SHADER_PARAM']['value']][0]
self.data.update_setting_value('shader', 'SHADER_PARAM', options[(current_index - 1) % len(options) ]) self.data.update_setting_value('shader', 'SHADER_PARAM', options[(current_index - 1) % len(options)])
self.message_handler.set_message('INFO', 'The Param amount is now ' + str(self.data.settings['shader']['SHADER_PARAM']['value'])) self.message_handler.set_message('INFO', 'The Param amount is now ' + str(self.data.settings['shader']['SHADER_PARAM']['value']))
def set_fixed_length(self, value): def set_fixed_length(self, value):
@@ -808,7 +794,6 @@ class Actions(object):
self.message_handler.set_message('INFO', 'tap: ■ ; < > : back') self.message_handler.set_message('INFO', 'tap: ■ ; < > : back')
self.fixed_length_setter = length_setter.FixedLengthSetter(self.data) self.fixed_length_setter = length_setter.FixedLengthSetter(self.data)
def return_to_default_control_mode(self): def return_to_default_control_mode(self):
display_list = self.data.get_display_modes_list(with_nav_mode=True) display_list = self.data.get_display_modes_list(with_nav_mode=True)
for display, control in display_list: for display, control in display_list:
@@ -829,10 +814,10 @@ class Actions(object):
self.message_handler.set_message('INFO', 'confirm: {} ■:y < >:no'.format(action_title[:22])) self.message_handler.set_message('INFO', 'confirm: {} ■:y < >:no'.format(action_title[:22]))
def confirm_shutdown(self): def confirm_shutdown(self):
self.start_confirm_action('shutdown_pi' ) self.start_confirm_action('shutdown_pi')
def confirm_quit(self): def confirm_quit(self):
self.start_confirm_action('quit_the_program', message='quit' ) self.start_confirm_action('quit_the_program', message='quit')
def confirm_switch_dev_mode(self, state): def confirm_switch_dev_mode(self, state):
# i startd writing a confirm dev mod but it messed with the state if you say no ... # i startd writing a confirm dev mod but it messed with the state if you say no ...
@@ -843,7 +828,6 @@ class Actions(object):
self.fixed_length_setter.record_input() self.fixed_length_setter.record_input()
self.display.settings_menu.generate_settings_list() self.display.settings_menu.generate_settings_list()
def setup_osc_server(self): def setup_osc_server(self):
server_parser = argparse.ArgumentParser() server_parser = argparse.ArgumentParser()
server_parser.add_argument("--ip", default="127.0.0.1", help="the ip") server_parser.add_argument("--ip", default="127.0.0.1", help="the ip")
@@ -861,7 +845,7 @@ class Actions(object):
this_dispatcher.map("/detour/detour_info", self.receive_detour_info) this_dispatcher.map("/detour/detour_info", self.receive_detour_info)
this_dispatcher.map("/capture/recording_finished", self.capture.receive_recording_finished) this_dispatcher.map("/capture/recording_finished", self.capture.receive_recording_finished)
this_dispatcher.map("/shutdown", self.exit_osc_server) this_dispatcher.map("/shutdown", self.exit_osc_server)
#this_dispatcher.map("/player/a/status", self.set_status) # this_dispatcher.map("/player/a/status", self.set_status)
osc_server.ThreadingOSCUDPServer.allow_reuse_address = True osc_server.ThreadingOSCUDPServer.allow_reuse_address = True
server = osc_server.ThreadingOSCUDPServer((server_args.ip, server_args.port), this_dispatcher) server = osc_server.ThreadingOSCUDPServer((server_args.ip, server_args.port), this_dispatcher)
@@ -892,7 +876,7 @@ class Actions(object):
self.data.update_setting_value('user_input', 'OSC_INPUT', 'disabled') self.data.update_setting_value('user_input', 'OSC_INPUT', 'disabled')
self.tk.after(2000, self.toggle_access_point_delay, setting_value, osc_setting_state) self.tk.after(2000, self.toggle_access_point_delay, setting_value, osc_setting_state)
def toggle_access_point_delay(self, setting_value, osc_setting_state ): def toggle_access_point_delay(self, setting_value, osc_setting_state):
if setting_value == 'enabled': if setting_value == 'enabled':
subprocess.call(['sudo', 'bash', '/home/pi/raspiApWlanScripts/switchToAP.sh']) subprocess.call(['sudo', 'bash', '/home/pi/raspiApWlanScripts/switchToAP.sh'])
else: else:
@@ -914,7 +898,6 @@ class Actions(object):
def enable_osc(self, osc_setting_state): def enable_osc(self, osc_setting_state):
self.data.update_setting_value('user_input', 'OSC_INPUT', osc_setting_state) self.data.update_setting_value('user_input', 'OSC_INPUT', osc_setting_state)
def show_ip(self, *args): def show_ip(self, *args):
address = self.data.get_ip_address() address = self.data.get_ip_address()
self.message_handler.set_message('INFO', 'ip is {}:8080'.format(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.kill()
self.serial_port_process = None self.serial_port_process = None
def stop_remote_process(self): def stop_remote_process(self):
if self.remote_process is not None: if self.remote_process is not None:
self.remote_process.kill() self.remote_process.kill()
@@ -948,7 +930,7 @@ class Actions(object):
self.stop_openframeworks_process() self.stop_openframeworks_process()
self._refresh_frame_buffer() self._refresh_frame_buffer()
self.check_if_should_start_openframeworks() self.check_if_should_start_openframeworks()
#self.tk.after(1000, self.check_if_should_start_openframeworks) # self.tk.after(1000, self.check_if_should_start_openframeworks)
else: else:
self._refresh_frame_buffer() self._refresh_frame_buffer()
@@ -960,7 +942,7 @@ class Actions(object):
subprocess.call(['killall', 'c_o_n_j_u_r']) subprocess.call(['killall', 'c_o_n_j_u_r'])
def try_pull_code_and_reset(self): def try_pull_code_and_reset(self):
#self.message_handler.set_message('INFO', 'checkin fo updates pls wait') # self.message_handler.set_message('INFO', 'checkin fo updates pls wait')
recur_repo = git.Repo("~/r_e_c_u_r") recur_repo = git.Repo("~/r_e_c_u_r")
conjur_repo = git.Repo(self.data.PATH_TO_OPENFRAMEWORKS + "apps/myApps/c_o_n_j_u_r") conjur_repo = git.Repo(self.data.PATH_TO_OPENFRAMEWORKS + "apps/myApps/c_o_n_j_u_r")
ofxVideoArtTools_repo = git.Repo(self.data.PATH_TO_OPENFRAMEWORKS + "/addons/ofxVideoArtTools") ofxVideoArtTools_repo = git.Repo(self.data.PATH_TO_OPENFRAMEWORKS + "/addons/ofxVideoArtTools")
@@ -968,7 +950,7 @@ class Actions(object):
current_conjur_hash = conjur_repo.head.object.hexsha current_conjur_hash = conjur_repo.head.object.hexsha
current_ofxVideoArtTools_hash = ofxVideoArtTools_repo.head.object.hexsha current_ofxVideoArtTools_hash = ofxVideoArtTools_repo.head.object.hexsha
self.data.try_remove_file(self.data.PATH_TO_DATA_OBJECTS + self.data.SETTINGS_JSON ) self.data.try_remove_file(self.data.PATH_TO_DATA_OBJECTS + self.data.SETTINGS_JSON)
self.data.try_remove_file(self.data.PATH_TO_DEFAULT_CONJUR_DATA) self.data.try_remove_file(self.data.PATH_TO_DEFAULT_CONJUR_DATA)
try: try:
recur_repo.remotes.origin.pull() recur_repo.remotes.origin.pull()
@@ -982,22 +964,22 @@ class Actions(object):
error_info = e.message error_info = e.message
else: else:
error_info = e error_info = e
self.message_handler.set_message('ERROR',error_info) self.message_handler.set_message('ERROR', error_info)
return return
new_recur_hash = recur_repo.head.object.hexsha new_recur_hash = recur_repo.head.object.hexsha
new_conjur_hash = conjur_repo.head.object.hexsha new_conjur_hash = conjur_repo.head.object.hexsha
new_ofxVideoArtTools_hash = ofxVideoArtTools_repo.head.object.hexsha new_ofxVideoArtTools_hash = ofxVideoArtTools_repo.head.object.hexsha
if current_recur_hash != new_recur_hash or current_conjur_hash != new_conjur_hash or current_ofxVideoArtTools_hash != new_ofxVideoArtTools_hash : if current_recur_hash != new_recur_hash or current_conjur_hash != new_conjur_hash or current_ofxVideoArtTools_hash != new_ofxVideoArtTools_hash:
#something has changed! # something has changed!
self.restart_the_program() self.restart_the_program()
else: else:
self.message_handler.set_message('INFO', 'up to date !') self.message_handler.set_message('INFO', 'up to date !')
# def complie_openframeworks(self): # def complie_openframeworks(self):
# subprocess.call(['make', '--directory=' + self.data.PATH_TO_OPENFRAMEWORKS + 'apps/myApps/c_o_n_j_u_r' ]) # subprocess.call(['make', '--directory=' + self.data.PATH_TO_OPENFRAMEWORKS + 'apps/myApps/c_o_n_j_u_r' ])
# self.message_handler.set_message('INFO', 'finished compiling!') # self.message_handler.set_message('INFO', 'finished compiling!')
# self.restart_the_program() # self.restart_the_program()
def shutdown_pi(self): def shutdown_pi(self):
subprocess.call(['sudo', 'shutdown', '-h', 'now']) subprocess.call(['sudo', 'shutdown', '-h', 'now'])
@@ -1005,7 +987,7 @@ class Actions(object):
def clear_message(self): def clear_message(self):
self.message_handler.clear_all_messages() self.message_handler.clear_all_messages()
#"""def modulate_param_layer_offset_to_amount(self, param, layer, amount): # """def modulate_param_layer_offset_to_amount(self, param, layer, amount):
# self.shaders.modulate_param_layer_offset_to_amount(param, amount, layer_offset=layer)""" # self.shaders.modulate_param_layer_offset_to_amount(param, amount, layer_offset=layer)"""
@staticmethod @staticmethod
@@ -1019,32 +1001,31 @@ class Actions(object):
subprocess.call(['sudo', 'eject', '/dev/sda{}'.format(i)]) subprocess.call(['sudo', 'eject', '/dev/sda{}'.format(i)])
self.message_handler.set_message('INFO', 'usb ejected') self.message_handler.set_message('INFO', 'usb ejected')
# TODO: make this interrogate the various components for available routes to parse # TODO: make this interrogate the various components for available routes to parse
# this would include eg a custom script module.. # this would include eg a custom script module..
@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_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"^select_next_shader_modulation_slot$", self.shaders.select_next_shader_modulation_slot ), (r"^select_next_shader_modulation_slot$", self.shaders.select_next_shader_modulation_slot),
( r"^select_previous_shader_modulation_slot$", self.shaders.select_previous_shader_modulation_slot ), (r"^select_previous_shader_modulation_slot$", self.shaders.select_previous_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),
( r"^set_display_mode_([a-zA-Z_]*)$", self.set_display_mode ) (r"^set_display_mode_([a-zA-Z_]*)$", self.set_display_mode)
} }
def detect_types(self, args): def detect_types(self, args):
a = [ int(arg) if str(arg).isnumeric() else str(arg) for arg in list(args) ] a = [int(arg) if str(arg).isnumeric() else str(arg) for arg in list(args)]
return a return a
def get_callback_for_method(self, method_name, argument): def get_callback_for_method(self, method_name, argument):
@@ -1055,7 +1036,7 @@ class Actions(object):
if matches: if matches:
found_method = me found_method = me
parsed_args = self.detect_types(matches.groups()) #list(map(int,matches.groups())) parsed_args = self.detect_types(matches.groups()) # list(map(int,matches.groups()))
if argument is not None: if argument is not None:
args = parsed_args + [argument] args = parsed_args + [argument]
else: else:
@@ -1089,29 +1070,28 @@ class Actions(object):
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)
break # only deal with the first plugin break # only deal with the first plugin
if method is None: if method is None:
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 return
try: try:
#print ("for method_name %s, arguments is %s and len is %s, got method %s" % (method_name, arguments, len(signature(method).parameters), method)) # print ("for method_name %s, arguments is %s and len is %s, got method %s" % (method_name, arguments, len(signature(method).parameters), method))
# for the case where cc is being used as switch, we ignore note_off # for the case where cc is being used as switch, we ignore note_off
#print(type(argument)) # print(type(argument))
if len(signature(method).parameters) == 0 and isinstance(argument, float) and argument == 0: if len(signature(method).parameters) == 0 and isinstance(argument, float) and argument == 0:
print('cc off ?') print('cc off ?')
return return
if arguments is not None and len(signature(method).parameters)==len(arguments): # only pass arguments if count matches method sig if arguments is not None and len(signature(method).parameters) == len(arguments): # only pass arguments if count matches method sig
method(*arguments) method(*arguments)
else: else:
method() method()
except: except:
print ("Exception calling action for '%s' with arguments ( %s ) " % ( method_name, arguments)) print("Exception calling action for '%s' with arguments ( %s ) " % (method_name, arguments))
import traceback import traceback
traceback.print_exc() traceback.print_exc()

View File

@@ -21,7 +21,7 @@ class AsyncWrite(threading.Thread):
def run(self): def run(self):
with open(self.filename, "w+") as data_file: with open(self.filename, "w+") as data_file:
if self.mode=='json': if self.mode == 'json':
json.dump(self.data, data_file, indent=4, sort_keys=True) json.dump(self.data, data_file, indent=4, sort_keys=True)
else: else:
data_file.write(self.data) data_file.write(self.data)
@@ -29,7 +29,6 @@ class AsyncWrite(threading.Thread):
class Data(object): class Data(object):
BANK_DATA_JSON = 'display_data.json' BANK_DATA_JSON = 'display_data.json'
SHADER_BANK_DATA_JSON = 'shader_bank_data.json' SHADER_BANK_DATA_JSON = 'shader_bank_data.json'
SETTINGS_JSON = 'settings.json' SETTINGS_JSON = 'settings.json'
@@ -49,10 +48,10 @@ class Data(object):
def __init__(self, message_handler): def __init__(self, message_handler):
self.message_handler = message_handler self.message_handler = message_handler
#self.EMPTY_BANK = [self.EMPTY_SLOT for i in range(10)] # self.EMPTY_BANK = [self.EMPTY_SLOT for i in range(10)]
self.PATHS_TO_BROWSER = [self.PATH_TO_EXTERNAL_DEVICES, '/home/pi/Videos' ] self.PATHS_TO_BROWSER = [self.PATH_TO_EXTERNAL_DEVICES, '/home/pi/Videos']
self.PATHS_TO_SHADERS = [self.PATH_TO_EXTERNAL_DEVICES, '/home/pi/r_e_c_u_r/Shaders', '/home/pi/Shaders' ] self.PATHS_TO_SHADERS = [self.PATH_TO_EXTERNAL_DEVICES, '/home/pi/r_e_c_u_r/Shaders', '/home/pi/Shaders']
self.PATHS_TO_PLUGIN_DATA = [ '/home/pi/r_e_c_u_r/json_objects/plugins', self.PATH_TO_EXTERNAL_DEVICES ] self.PATHS_TO_PLUGIN_DATA = ['/home/pi/r_e_c_u_r/json_objects/plugins', self.PATH_TO_EXTERNAL_DEVICES]
### state data ### state data
self.auto_repeat_on = True self.auto_repeat_on = True
@@ -70,7 +69,7 @@ class Data(object):
self.feedback_active = False self.feedback_active = False
self.detour_active = False self.detour_active = False
self.detour_mix_shaders = self.get_list_of_two_input_shaders() self.detour_mix_shaders = self.get_list_of_two_input_shaders()
self.detour_settings = collections.OrderedDict([('current_detour',0), ('is_playing', False), ('is_recording', False), ('record_loop', False), ('detour_size', False), ('detour_speed', 0), ('memory_full', False), ('mix_shader', self.detour_mix_shaders[0]), ('detour_position', 5), ('detour_start', 0), ('detour_end', 0), ('detour_mix', 0), ('is_delay', False)]) self.detour_settings = collections.OrderedDict([('current_detour', 0), ('is_playing', False), ('is_recording', False), ('record_loop', False), ('detour_size', False), ('detour_speed', 0), ('memory_full', False), ('mix_shader', self.detour_mix_shaders[0]), ('detour_position', 5), ('detour_start', 0), ('detour_end', 0), ('detour_mix', 0), ('is_delay', False)])
self.next_bankslot = '0-0' self.next_bankslot = '0-0'
self.current_bankslot = '0-0' self.current_bankslot = '0-0'
@@ -79,7 +78,7 @@ class Data(object):
### persisted data (use default if doesnt exits): ### persisted data (use default if doesnt exits):
if not os.path.isfile(self.PATH_TO_CONJUR_DATA): if not os.path.isfile(self.PATH_TO_CONJUR_DATA):
self.try_remove_file(self.PATH_TO_DATA_OBJECTS + self.SETTINGS_JSON ) # keep the, in sync self.try_remove_file(self.PATH_TO_DATA_OBJECTS + self.SETTINGS_JSON) # keep the, in sync
copyfile(self.PATH_TO_DEFAULT_CONJUR_DATA, self.PATH_TO_CONJUR_DATA) copyfile(self.PATH_TO_DEFAULT_CONJUR_DATA, self.PATH_TO_CONJUR_DATA)
self.bank_data = [self.create_empty_bank()] self.bank_data = [self.create_empty_bank()]
@@ -113,15 +112,15 @@ class Data(object):
docs.generate_mappings_doc("OSC mappings", self.osc_mappings, column_one_header="OSC address") docs.generate_mappings_doc("OSC mappings", self.osc_mappings, column_one_header="OSC address")
docs.generate_mappings_doc("Analog mappings", self.analog_mappings, column_one_header="Analogue input") docs.generate_mappings_doc("Analog mappings", self.analog_mappings, column_one_header="Analogue input")
docs.generate_mappings_doc("Key mappings", self.key_mappings, column_one_header="Key mappings") docs.generate_mappings_doc("Key mappings", self.key_mappings, column_one_header="Key mappings")
#quit() # quit()
def initialise_plugins(self): def initialise_plugins(self):
#initialise plugin manager # initialise plugin manager
self.plugins = plugin_collection.PluginCollection("plugins", self.message_handler, self) self.plugins = plugin_collection.PluginCollection("plugins", self.message_handler, self)
self.compare_plugins_list() self.compare_plugins_list()
def get_enabled_plugin_class_names(self): def get_enabled_plugin_class_names(self):
return [k for k,v in self.enabled_plugins.items() if v is True] return [k for k, v in self.enabled_plugins.items() if v is True]
def compare_plugins_list(self): def compare_plugins_list(self):
current_plugins = [type(plugin).__name__ for plugin in self.plugins.get_plugins(include_disabled=True)] current_plugins = [type(plugin).__name__ for plugin in self.plugins.get_plugins(include_disabled=True)]
@@ -131,9 +130,9 @@ class Data(object):
self.enabled_plugins.pop(k, None) self.enabled_plugins.pop(k, None)
for k in plugins_to_add: for k in plugins_to_add:
self.enabled_plugins[k] = False self.enabled_plugins[k] = False
#switch off all plugins if disabled ... # switch off all plugins if disabled ...
if self.settings['system']['USE_PLUGINS']['value'] == 'disabled': if self.settings['system']['USE_PLUGINS']['value'] == 'disabled':
self.enabled_plugins = {x:False for x in self.enabled_plugins} self.enabled_plugins = {x: False for x in self.enabled_plugins}
def update_enabled_plugins(self, key, value): def update_enabled_plugins(self, key, value):
self.enabled_plugins[key] = value self.enabled_plugins[key] = value
@@ -141,13 +140,13 @@ class Data(object):
def load_midi_mapping_for_device(self, device_name): def load_midi_mapping_for_device(self, device_name):
# check if custom config file exists on disk for this device name # check if custom config file exists on disk for this device name
custom_file = self.MIDI_MAPPING_JSON.replace(".json","_%s.json"%device_name) custom_file = self.MIDI_MAPPING_JSON.replace(".json", "_%s.json" % device_name)
if os.path.isfile(self.PATH_TO_DATA_OBJECTS + custom_file): if os.path.isfile(self.PATH_TO_DATA_OBJECTS + custom_file):
self.midi_mappings = self._read_json(custom_file) self.midi_mappings = self._read_json(custom_file)
self.message_handler.set_message('INFO', "Loaded %s for %s" % (custom_file, device_name)) self.message_handler.set_message('INFO', "Loaded %s for %s" % (custom_file, device_name))
print ("loaded custom midi mapping for %s" % custom_file) print("loaded custom midi mapping for %s" % custom_file)
else: else:
print ("loading default midi mapping for %s" % (device_name)) print("loading default midi mapping for %s" % (device_name))
self.midi_mappings = self._read_json(self.MIDI_MAPPING_JSON) self.midi_mappings = self._read_json(self.MIDI_MAPPING_JSON)
return self.midi_mappings return self.midi_mappings
@@ -187,15 +186,15 @@ class Data(object):
for path in self.PATHS_TO_PLUGIN_DATA: for path in self.PATHS_TO_PLUGIN_DATA:
print("loading plugin data %s" % path) print("loading plugin data %s" % path)
try: try:
with open("%s/%s" % (path,file_name)) as data_file: with open("%s/%s" % (path, file_name)) as data_file:
data = json.load(data_file) data = json.load(data_file)
return data return data
except: except:
pass pass
print ("no plugin data loaded for %s" % file_name) print("no plugin data loaded for %s" % file_name)
def _update_plugin_json(self, file_name, data): def _update_plugin_json(self, file_name, data):
#with open("%s/%s" % (self.PATHS_TO_PLUGIN_DATA[0], file_name), "w+") as data_file: # with open("%s/%s" % (self.PATHS_TO_PLUGIN_DATA[0], file_name), "w+") as data_file:
# json.dump(data, data_file, indent=4, sort_keys=True) # json.dump(data, data_file, indent=4, sort_keys=True)
writer = AsyncWrite("%s/%s" % (self.PATHS_TO_PLUGIN_DATA[0], file_name), data, mode='json') writer = AsyncWrite("%s/%s" % (self.PATHS_TO_PLUGIN_DATA[0], file_name), data, mode='json')
writer.start() writer.start()
@@ -220,12 +219,12 @@ class Data(object):
tree.write(self.PATH_TO_CONJUR_DATA) tree.write(self.PATH_TO_CONJUR_DATA)
def get_setting_and_folder_from_name(self, setting_name): def get_setting_and_folder_from_name(self, setting_name):
for folder_key , folder_item in self.settings.items(): for folder_key, folder_item in self.settings.items():
for setting_key, setting_item in folder_item.items(): for setting_key, setting_item in folder_item.items():
if setting_key == setting_name: if setting_key == setting_name:
return folder_key, setting_key, setting_item return folder_key, setting_key, setting_item
##### setting and adding to sample mapping ###### ##### setting and adding to sample mapping ######
def create_new_slot_mapping_in_first_open(self, file_name): def create_new_slot_mapping_in_first_open(self, file_name):
######## used for mapping current video to next available slot ######## ######## used for mapping current video to next available slot ########
@@ -238,7 +237,7 @@ class Data(object):
def create_new_slot_mapping(self, slot_number, file_name): def create_new_slot_mapping(self, slot_number, file_name):
######## used for mapping current video to a specific slot ######## ######## used for mapping current video to a specific slot ########
has_location, location = self._get_path_for_file(file_name) has_location, location = self._get_path_for_file(file_name)
print('file_name:{},has_location:{}, location:{}'.format(file_name,has_location, location)) print('file_name:{},has_location:{}, location:{}'.format(file_name, has_location, location))
length = self._get_length_for_file(location) length = self._get_length_for_file(location)
if length: if length:
new_slot = dict(name=file_name, location=location, length=length, start=-1, end=-1, rate=1) new_slot = dict(name=file_name, location=location, length=length, start=-1, end=-1, rate=1)
@@ -250,13 +249,13 @@ class Data(object):
def update_bank_number_by_amount(self, amount): def update_bank_number_by_amount(self, amount):
empty_bank = self.create_empty_bank() empty_bank = self.create_empty_bank()
if(self.bank_data[-1] != empty_bank): if (self.bank_data[-1] != empty_bank):
self.bank_data.append(empty_bank) self.bank_data.append(empty_bank)
elif(len(self.bank_data) > 1): elif (len(self.bank_data) > 1):
if self.bank_data[-2] == empty_bank: if self.bank_data[-2] == empty_bank:
self.bank_data.pop() self.bank_data.pop()
self._update_json(self.BANK_DATA_JSON, self.bank_data) self._update_json(self.BANK_DATA_JSON, self.bank_data)
self.bank_number = (self.bank_number+amount)%(len(self.bank_data)) self.bank_number = (self.bank_number + amount) % (len(self.bank_data))
def update_next_slot_number(self, new_value, is_current=False): def update_next_slot_number(self, new_value, is_current=False):
if self.bank_data[self.bank_number][new_value]['location'] == '': if self.bank_data[self.bank_number][new_value]['location'] == '':
@@ -266,15 +265,14 @@ class Data(object):
self.message_handler.set_message('INFO', 'no device found for this slot') self.message_handler.set_message('INFO', 'no device found for this slot')
return False return False
elif is_current: elif is_current:
self.current_bankslot = '{}-{}'.format(self.bank_number,new_value) self.current_bankslot = '{}-{}'.format(self.bank_number, new_value)
return True return True
else: else:
self.next_bankslot = '{}-{}'.format(self.bank_number,new_value) self.next_bankslot = '{}-{}'.format(self.bank_number, new_value)
return True return True
######## setting and adding to shader mapping ######## setting and adding to shader mapping
def create_new_shader_mapping_in_first_open(self, file_name): def create_new_shader_mapping_in_first_open(self, file_name):
######## used for mapping current shader to next available slot ######## ######## used for mapping current shader to next available slot ########
for index, slot in enumerate(self.shader_bank_data[self.shader_layer]): for index, slot in enumerate(self.shader_bank_data[self.shader_layer]):
@@ -286,7 +284,7 @@ class Data(object):
def create_new_shader_mapping(self, slot_number, file_name): def create_new_shader_mapping(self, slot_number, file_name):
######## used for mapping current shader to a specific slot ######## ######## used for mapping current shader to a specific slot ########
has_location, location = self._get_path_for_file(file_name) has_location, location = self._get_path_for_file(file_name)
print('file_name:{},has_location:{}, location:{}'.format(file_name,has_location, location)) print('file_name:{},has_location:{}, location:{}'.format(file_name, has_location, location))
new_slot = dict(name=file_name, path=location, shad_type='-', param_number=4) new_slot = dict(name=file_name, path=location, shad_type='-', param_number=4)
self._update_a_shader_slots_data(slot_number, new_slot) self._update_a_shader_slots_data(slot_number, new_slot)
@@ -297,8 +295,6 @@ class Data(object):
def update_shader_layer_by_amount(self, amount): def update_shader_layer_by_amount(self, amount):
self.shader_layer = (self.shader_layer + amount) % len(self.shader_bank_data) self.shader_layer = (self.shader_layer + amount) % len(self.shader_bank_data)
def update_setting_value(self, setting_folder, setting_name, setting_value): def update_setting_value(self, setting_folder, setting_name, setting_value):
self.settings[setting_folder][setting_name]['value'] = setting_value self.settings[setting_folder][setting_name]['value'] = setting_value
self._update_json(self.SETTINGS_JSON, self.settings) self._update_json(self.SETTINGS_JSON, self.settings)
@@ -307,16 +303,16 @@ class Data(object):
@classmethod @classmethod
def split_bankslot_number(cls, bankslot_number): def split_bankslot_number(cls, bankslot_number):
split = bankslot_number.split('-') split = bankslot_number.split('-')
is_bank_num_int , converted_bank_number = cls.try_convert_string_to_int(split[0]) is_bank_num_int, converted_bank_number = cls.try_convert_string_to_int(split[0])
is_slot_num_int , converted_slot_number = cls.try_convert_string_to_int(split[1]) is_slot_num_int, converted_slot_number = cls.try_convert_string_to_int(split[1])
return converted_bank_number, converted_slot_number return converted_bank_number, converted_slot_number
@staticmethod @staticmethod
def try_convert_string_to_int(string_input): def try_convert_string_to_int(string_input):
try: try:
return True , int(string_input) return True, int(string_input)
except ValueError: except ValueError:
return False , '*' return False, '*'
def get_next_context(self, is_current=False): def get_next_context(self, is_current=False):
######## loads the slot details, uses settings to modify them and then set next slot number ######## ######## loads the slot details, uses settings to modify them and then set next slot number ########
@@ -324,7 +320,7 @@ class Data(object):
bankslot_number = self.current_bankslot bankslot_number = self.current_bankslot
else: else:
bankslot_number = self.next_bankslot bankslot_number = self.next_bankslot
bank_num , slot_num = self.split_bankslot_number(bankslot_number) bank_num, slot_num = self.split_bankslot_number(bankslot_number)
next_slot_details = self.bank_data[bank_num][slot_num] next_slot_details = self.bank_data[bank_num][slot_num]
start_value = next_slot_details['start'] start_value = next_slot_details['start']
@@ -354,15 +350,15 @@ class Data(object):
new_start = start new_start = start
if use_fixed_length and use_rand_start: if use_fixed_length and use_rand_start:
max_increase = int(max(end - start - max(total_fixed_length, 4),0)) max_increase = int(max(end - start - max(total_fixed_length, 4), 0))
random_increase = randint(0,max_increase) random_increase = randint(0, max_increase)
new_start = start + random_increase new_start = start + random_increase
new_end = min(new_start + total_fixed_length, end) new_end = min(new_start + total_fixed_length, end)
elif use_fixed_length and not use_rand_start: elif use_fixed_length and not use_rand_start:
new_end = min(new_start + total_fixed_length, end) new_end = min(new_start + total_fixed_length, end)
elif not use_fixed_length and use_rand_start: elif not use_fixed_length and use_rand_start:
max_increase = int(max(end - start - 4,0)) max_increase = int(max(end - start - 4, 0))
random_increase = randint(0,max_increase) random_increase = randint(0, max_increase)
new_start = start + random_increase new_start = start + random_increase
return new_start, new_end return new_start, new_end
@@ -372,16 +368,16 @@ class Data(object):
loaded_slots = self._get_list_of_loaded_slots_in_current_bank() loaded_slots = self._get_list_of_loaded_slots_in_current_bank()
if loaded_slots: if loaded_slots:
if next_setting == 'random': if next_setting == 'random':
next_slot = loaded_slots[randint(0,len(loaded_slots)-1)] next_slot = loaded_slots[randint(0, len(loaded_slots) - 1)]
elif next_setting == 'consecutive': elif next_setting == 'consecutive':
next_slot = self.get_next_loaded_slot(slot_num, loaded_slots) next_slot = self.get_next_loaded_slot(slot_num, loaded_slots)
else: else:
next_slot = slot_num next_slot = slot_num
if is_current: if is_current:
self.current_bankslot = '{}-{}'.format(self.bank_number,next_slot) self.current_bankslot = '{}-{}'.format(self.bank_number, next_slot)
else: else:
self.next_bankslot = '{}-{}'.format(self.bank_number,next_slot) self.next_bankslot = '{}-{}'.format(self.bank_number, next_slot)
def _get_list_of_loaded_slots_in_current_bank(self): def _get_list_of_loaded_slots_in_current_bank(self):
list_of_loaded_slots = [] list_of_loaded_slots = []
@@ -392,9 +388,9 @@ class Data(object):
@staticmethod @staticmethod
def get_next_loaded_slot(current_slot, loaded_slots): def get_next_loaded_slot(current_slot, loaded_slots):
i = ( current_slot + 1 ) % len(loaded_slots) i = (current_slot + 1) % len(loaded_slots)
while(i not in loaded_slots): while (i not in loaded_slots):
i = ( i + 1 ) % len(loaded_slots) i = (i + 1) % len(loaded_slots)
return i return i
def update_slot_start_to_this_time(self, slot_number, position): def update_slot_start_to_this_time(self, slot_number, position):
@@ -410,7 +406,7 @@ class Data(object):
self._update_json(self.BANK_DATA_JSON, self.bank_data) self._update_json(self.BANK_DATA_JSON, self.bank_data)
def open_omxplayer_for_reset(self): def open_omxplayer_for_reset(self):
self._get_length_for_file('/ss',no_message=True ) self._get_length_for_file('/ss', no_message=True)
def _get_length_for_file(self, path, no_message=False): def _get_length_for_file(self, path, no_message=False):
try: try:
@@ -419,12 +415,11 @@ class Data(object):
temp_player.quit() temp_player.quit()
return duration return duration
except Exception as e: except Exception as e:
print (e) print(e)
if not no_message: if not no_message:
self.message_handler.set_message('INFO', 'cannot load video') self.message_handler.set_message('INFO', 'cannot load video')
return None return None
def _get_path_for_file(self, file_name): def _get_path_for_file(self, file_name):
######## returns full path for a given file name ######## ######## returns full path for a given file name ########
for path in self.PATHS_TO_BROWSER + self.PATHS_TO_SHADERS: 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 True, '{}/{}'.format(root, file_name)
return False, '' return False, ''
def is_this_path_broken(self, path): def is_this_path_broken(self, path):
external_devices = os.listdir(self.PATH_TO_EXTERNAL_DEVICES) external_devices = os.listdir(self.PATH_TO_EXTERNAL_DEVICES)
has_device_in_path = self.PATH_TO_EXTERNAL_DEVICES in path has_device_in_path = self.PATH_TO_EXTERNAL_DEVICES in path
@@ -446,35 +440,35 @@ class Data(object):
def get_background_colour(self): def get_background_colour(self):
colour_name = self.settings['video']['BACKGROUND_COLOUR']['value'] colour_name = self.settings['video']['BACKGROUND_COLOUR']['value']
colour_argb = (255,0,0,0) colour_argb = (255, 0, 0, 0)
if colour_name == "black": if colour_name == "black":
colour_argb = (255,0,0,0) colour_argb = (255, 0, 0, 0)
elif colour_name == "white": elif colour_name == "white":
colour_argb = (255,255,255,255) colour_argb = (255, 255, 255, 255)
elif colour_name == "green": elif colour_name == "green":
colour_argb = (255,0,255,0) colour_argb = (255, 0, 255, 0)
elif colour_name == "blue": elif colour_name == "blue":
colour_argb = (255,0,0,255) colour_argb = (255, 0, 0, 255)
elif colour_name == "pink": elif colour_name == "pink":
colour_argb = (255,255,0,255) colour_argb = (255, 255, 0, 255)
elif colour_name == "none": elif colour_name == "none":
colour_argb = (0,0,0,0) colour_argb = (0, 0, 0, 0)
colour_hex = '%02x%02x%02x%02x' % colour_argb colour_hex = '%02x%02x%02x%02x' % colour_argb
return colour_hex return colour_hex
def get_display_modes_list(self, with_nav_mode=False): def get_display_modes_list(self, with_nav_mode=False):
display_modes = [[ "SAMPLER",'PLAYER'], ["BROWSER",'NAV_BROWSER'],["SETTINGS",'NAV_SETTINGS']] display_modes = [["SAMPLER", 'PLAYER'], ["BROWSER", 'NAV_BROWSER'], ["SETTINGS", 'NAV_SETTINGS']]
if self.settings['video']['VIDEOPLAYER_BACKEND']['value'] != 'omxplayer' and self.settings['shader']['USE_SHADER']['value'] == 'enabled': if self.settings['video']['VIDEOPLAYER_BACKEND']['value'] != 'omxplayer' and self.settings['shader']['USE_SHADER']['value'] == 'enabled':
display_modes.append(["SHADERS",'NAV_SHADERS']) display_modes.append(["SHADERS", 'NAV_SHADERS'])
if self.settings['shader']['USE_SHADER_BANK']['value'] == 'enabled' and ["SHADERS",'NAV_SHADERS'] in display_modes: if self.settings['shader']['USE_SHADER_BANK']['value'] == 'enabled' and ["SHADERS", 'NAV_SHADERS'] in display_modes:
display_modes.append(["SHDR_BNK",'PLAY_SHADER']) display_modes.append(["SHDR_BNK", 'PLAY_SHADER'])
if self.settings['shader']['USE_SHADER_MOD']['value'] == 'enabled' and ["SHADERS",'NAV_SHADERS'] in display_modes: if self.settings['shader']['USE_SHADER_MOD']['value'] == 'enabled' and ["SHADERS", 'NAV_SHADERS'] in display_modes:
display_modes.append(["SHDR_MOD",["NAV_MOD","PLAY_SHADER"]]) ## allow override, but fall back to PLAY_SHADER controls display_modes.append(["SHDR_MOD", ["NAV_MOD", "PLAY_SHADER"]]) ## allow override, but fall back to PLAY_SHADER controls
if self.settings['detour']['TRY_DEMO']['value'] == 'enabled': if self.settings['detour']['TRY_DEMO']['value'] == 'enabled':
display_modes.append(["FRAMES",'NAV_DETOUR']) display_modes.append(["FRAMES", 'NAV_DETOUR'])
if self.settings['system'].setdefault('USE_PLUGINS', if self.settings['system'].setdefault('USE_PLUGINS',
self.default_settings.setdefault('USE_PLUGINS',{'value': 'enabled'})).get('value') == 'enabled': self.default_settings.setdefault('USE_PLUGINS', {'value': 'enabled'})).get('value') == 'enabled':
display_modes.append(["PLUGINS",'NAV_PLUGINS']) display_modes.append(["PLUGINS", 'NAV_PLUGINS'])
if hasattr(self, 'plugins') and self.plugins is not None: if hasattr(self, 'plugins') and self.plugins is not None:
from data_centre.plugin_collection import DisplayPlugin from data_centre.plugin_collection import DisplayPlugin
@@ -512,9 +506,9 @@ class Data(object):
if os.path.exists('/home/pi/r_e_c_u_r/Shaders/2-input'): if os.path.exists('/home/pi/r_e_c_u_r/Shaders/2-input'):
(_, _, filenames) = next(os.walk('/home/pi/r_e_c_u_r/Shaders/2-input')) (_, _, filenames) = next(os.walk('/home/pi/r_e_c_u_r/Shaders/2-input'))
return filenames return filenames
#elif os.path.exists('/home/pi/r_e_c_u_r/Shaders/2-input'): # elif os.path.exists('/home/pi/r_e_c_u_r/Shaders/2-input'):
#(_, _, filenames) = next(os.walk('/home/pi/r_e_c_u_r/Shaders/2-input')) # (_, _, filenames) = next(os.walk('/home/pi/r_e_c_u_r/Shaders/2-input'))
#return filenames # return filenames
else: else:
return [] return []
@@ -522,5 +516,3 @@ class Data(object):
def try_remove_file(path): def try_remove_file(path):
if os.path.exists(path): if os.path.exists(path):
os.remove(path) os.remove(path)

View File

@@ -1,5 +1,6 @@
import datetime import datetime
class FixedLengthSetter(object): class FixedLengthSetter(object):
DELTA_NUMBER = 2 DELTA_NUMBER = 2
@@ -17,6 +18,6 @@ class FixedLengthSetter(object):
self.list_of_deltas.append(now_time - self.last_time) self.list_of_deltas.append(now_time - self.last_time)
self.last_time = now_time self.last_time = now_time
if len(self.list_of_deltas) > self.DELTA_NUMBER: if len(self.list_of_deltas) > self.DELTA_NUMBER:
average_delta = sum(self.list_of_deltas[-self.DELTA_NUMBER+1:], datetime.timedelta(0))/float(self.DELTA_NUMBER) average_delta = sum(self.list_of_deltas[-self.DELTA_NUMBER + 1:], datetime.timedelta(0)) / float(self.DELTA_NUMBER)
average_seconds = round(average_delta.total_seconds(), 2) average_seconds = round(average_delta.total_seconds(), 2)
self.data.update_setting_value('sampler', 'FIXED_LENGTH', average_seconds) self.data.update_setting_value('sampler', 'FIXED_LENGTH', average_seconds)

View File

@@ -9,6 +9,7 @@ class Plugin(object):
"""Base class that each plugin must inherit from. within this class """Base class that each plugin must inherit from. within this class
you must define the methods that all of your plugins must implement you must define the methods that all of your plugins must implement
""" """
@property @property
def disabled(self): def disabled(self):
return type(self).__name__ not in self.pc.data.get_enabled_plugin_class_names() 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): def start_plugin(self):
print(">>Starting plugin " + type(self).__name__) print(">>Starting plugin " + type(self).__name__)
class MidiFeedbackPlugin(Plugin): class MidiFeedbackPlugin(Plugin):
"""Base class for MIDI feedback plugins """Base class for MIDI feedback plugins
""" """
def __init__(self, plugin_collection): def __init__(self, plugin_collection):
super().__init__(plugin_collection) super().__init__(plugin_collection)
self.description = 'Outputs feedback about status to device eg MIDI pads' self.description = 'Outputs feedback about status to device eg MIDI pads'
@@ -39,29 +42,32 @@ class MidiFeedbackPlugin(Plugin):
def refresh_midi_feedback(self): def refresh_midi_feedback(self):
raise NotImplementedError raise NotImplementedError
class SequencePlugin(Plugin): class SequencePlugin(Plugin):
"""Base class for plugins that run constantly or on demand for eg automation""" """Base class for plugins that run constantly or on demand for eg automation"""
def __init__(self, plugin_collection): def __init__(self, plugin_collection):
super().__init__(plugin_collection) super().__init__(plugin_collection)
@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):
#self.speed = 2.0 * (2.0*(speed-0.5)) # self.speed = 2.0 * (2.0*(speed-0.5))
speed = 2.0*(speed-0.5) # adjust to range -1 to +1 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 negative = speed < 0.0 # remember negative state cos we'll lose it in next
self.speed = (speed * speed) * 2.0 self.speed = (speed * speed) * 2.0
if negative: self.speed *= -1 if negative:
print ("automation speed is now %s" % self.speed) self.speed *= -1
print("automation speed is now %s" % self.speed)
def toggle_automation(self): def toggle_automation(self):
if not self.is_playing(): if not self.is_playing():
@@ -81,26 +87,28 @@ class SequencePlugin(Plugin):
def toggle_pause_automation(self): def toggle_pause_automation(self):
self.pause_flag = not self.is_paused() self.pause_flag = not self.is_paused()
self.last_delta = -1 self.last_delta = -1
#self.pause_flag = self.is_paused() and self.is_playing() # self.pause_flag = self.is_paused() and self.is_playing()
if not self.is_paused() and self.is_playing(): #not self.is_playing(): if not self.is_paused() and self.is_playing(): # not self.is_playing():
self.run_automation() self.run_automation()
last_delta = -1 last_delta = -1
def delta(self, now): def delta(self, now):
if self.last_delta==-1: if self.last_delta == -1:
self.last_delta = now self.last_delta = now
r = now - self.last_delta r = now - self.last_delta
self.last_delta = now self.last_delta = now
return r return r
speed = 0.25 #1.0 speed = 0.25 # 1.0
def move_delta(self, delta, speed): def move_delta(self, delta, speed):
self.position += delta * speed self.position += delta * speed
if self.position>1.0: if self.position > 1.0:
self.position = self.position-1.0 self.position = self.position - 1.0
self.iterations_count += 1 self.iterations_count += 1
elif self.position<0.0: elif self.position < 0.0:
self.position = self.position+1.0 self.position = self.position + 1.0
self.iterations_count += 1 self.iterations_count += 1
position = 0.0 position = 0.0
@@ -111,12 +119,13 @@ class SequencePlugin(Plugin):
iterations_count = 0 iterations_count = 0
duration = 2000 duration = 2000
frequency = 100 frequency = 100
def run_automation(self): def run_automation(self):
import time import time
now = time.time() now = time.time()
#print("running automation at %s!" % self.position) # print("running automation at %s!" % self.position)
if not self.is_paused(): if not self.is_paused():
self.store_passed = None self.store_passed = None
delta = self.delta(now) delta = self.delta(now)
@@ -126,9 +135,9 @@ class SequencePlugin(Plugin):
if not self.stop_flag and not self.disabled: if not self.stop_flag and not self.disabled:
self.pc.midi_input.root.after(self.frequency, self.run_automation) self.pc.midi_input.root.after(self.frequency, self.run_automation)
else: else:
#print("%s: stopping ! (stop_flag %s)" % ((now - self.automation_start),self.stop_flag) ) # print("%s: stopping ! (stop_flag %s)" % ((now - self.automation_start),self.stop_flag) )
self.stop_flag = False self.stop_flag = False
#self.automation_start = None # self.automation_start = None
self.iterations_count = 0 self.iterations_count = 0
def is_paused(self): def is_paused(self):
@@ -136,11 +145,12 @@ class SequencePlugin(Plugin):
def is_playing(self): def is_playing(self):
return not self.is_paused() or self.stop_flag return not self.is_paused() or self.stop_flag
#return self.automation_start is not None # return self.automation_start is not None
def run_sequence(self, position): def run_sequence(self, position):
raise NotImplementedError raise NotImplementedError
class ActionsPlugin(Plugin): class ActionsPlugin(Plugin):
def __init__(self, plugin_collection): def __init__(self, plugin_collection):
super().__init__(plugin_collection) super().__init__(plugin_collection)
@@ -148,7 +158,7 @@ class ActionsPlugin(Plugin):
@property @property
def parserlist(self): def parserlist(self):
return [ return [
#( r"^test_plugin$", self.test_plugin ) # ( r"^test_plugin$", self.test_plugin )
] ]
# test if this plugin should handle the method name -- also covers if we're a DisplayPlugin # test if this plugin should handle the method name -- also covers if we're a DisplayPlugin
@@ -158,7 +168,7 @@ class ActionsPlugin(Plugin):
return True return True
for a in self.parserlist: for a in self.parserlist:
if (a[0]==method_name): if (a[0] == method_name):
return True return True
regex = a[0] regex = a[0]
me = a[1] me = a[1]
@@ -185,8 +195,10 @@ class ActionsPlugin(Plugin):
return (found_method, args) return (found_method, args)
class DisplayPlugin(Plugin): class DisplayPlugin(Plugin):
"""Base class for plugins that want to show a user interface on the recur screen""" """Base class for plugins that want to show a user interface on the recur screen"""
def __init__(self, plugin_collection): def __init__(self, plugin_collection):
super().__init__(plugin_collection) super().__init__(plugin_collection)
@@ -198,11 +210,13 @@ class DisplayPlugin(Plugin):
def show_plugin(self, display): def show_plugin(self, display):
from tkinter import END from tkinter import END
#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):
"""Base class for plugins that want to be notified of a change to modulation values""" """Base class for plugins that want to be notified of a change to modulation values"""
def __init__(self, plugin_collection): def __init__(self, plugin_collection):
super().__init__(plugin_collection) super().__init__(plugin_collection)
@@ -210,8 +224,10 @@ class ModulationReceiverPlugin(Plugin):
print("||||||set_modulation_value dummy!") print("||||||set_modulation_value dummy!")
raise NotImplementedError raise NotImplementedError
class AutomationSourcePlugin(Plugin): class AutomationSourcePlugin(Plugin):
"""Base class for plugins that offer things to save&playback to&from automation""" """Base class for plugins that offer things to save&playback to&from automation"""
@property @property
def frame_key(self): def frame_key(self):
return self.__class__.__name__ return self.__class__.__name__
@@ -226,7 +242,7 @@ class AutomationSourcePlugin(Plugin):
raise NotImplementedError raise NotImplementedError
def get_frame_summary(self, data): def get_frame_summary(self, data):
line = self.__class__.name + "%s: %s"%(self.__class__.name,data) line = self.__class__.name + "%s: %s" % (self.__class__.name, data)
return line return line
# these frame stubs deal with the simplest case of a frame being a dict of values # these frame stubs deal with the simplest case of a frame being a dict of values
@@ -243,36 +259,36 @@ class AutomationSourcePlugin(Plugin):
return cf.copy() return cf.copy()
diff = {} diff = {}
for queue,message in cf.items(): for queue, message in cf.items():
if lf.get(queue) is None or lf.get(queue)!=message: if lf.get(queue) is None or lf.get(queue) != message:
diff[queue] = message diff[queue] = message
#print (">>>>>> returning diff\n%s\n<<<<<" % diff) # print (">>>>>> returning diff\n%s\n<<<<<" % diff)
return diff return diff
def merge_data(self, data1, data2): def merge_data(self, data1, data2):
#print (">>>merge_data passed\n\t%s\nand\n\t%s" % (data1,data2)) # print (">>>merge_data passed\n\t%s\nand\n\t%s" % (data1,data2))
output = {} output = {}
if data1 is None: if data1 is None:
output = data2.copy() output = data2.copy()
else: else:
output = data1.copy() output = data1.copy()
output.update(data2) output.update(data2)
#print("merge_data returning\n\t%s" % output) # print("merge_data returning\n\t%s" % output)
#print("<<<<<<") # print("<<<<<<")
return output return output
def get_ignored_data(self, data, ignored): def get_ignored_data(self, data, ignored):
#frame = self.f # frame = self.f
f = data.copy() #frame.get(self.frame_key,{}) f = data.copy() # frame.get(self.frame_key,{})
for queue,item in f.items(): #frame.get(self.frame_key,{}).items(): for queue, item in f.items(): # frame.get(self.frame_key,{}).items():
if ignored.get(queue) is not None: if ignored.get(queue) is not None:
#print ("\tfound that should ignore %s (%s) ?" % (queue, item)) # print ("\tfound that should ignore %s (%s) ?" % (queue, item))
f[queue] = None f[queue] = None
return f return f
def is_frame_data_empty(self, data): def is_frame_data_empty(self, data):
if len(data)>0: if len(data) > 0:
return False return False
return True return True
@@ -281,6 +297,7 @@ class AutomationSourcePlugin(Plugin):
### TODO: experimental value interpolation -- doesn't work, and is slow! ### TODO: experimental value interpolation -- doesn't work, and is slow!
cmd_size = {} cmd_size = {}
def process_interpolate_clip(self, frames): def process_interpolate_clip(self, frames):
# loop over every frame # loop over every frame
# for each property of each frame # for each property of each frame
@@ -290,9 +307,9 @@ class AutomationSourcePlugin(Plugin):
# else, # else,
# store as last value # store as last value
print("AutomationSourcePlugin[%s] got pre-interpolated clip: %s" % ( type(self), [ f.f for f in frames if f is not None]) ) print("AutomationSourcePlugin[%s] got pre-interpolated clip: %s" % (type(self), [f.f for f in frames if f is not None]))
#last = [ [None]*4, [None]*4, [None]*4 ] # last = [ [None]*4, [None]*4, [None]*4 ]
last = {} last = {}
"""for findex,frame in enumerate(frames): """for findex,frame in enumerate(frames):
@@ -300,17 +317,17 @@ class AutomationSourcePlugin(Plugin):
continue""" continue"""
reproc_to = 0 reproc_to = 0
queues = []# queue for queue in list(frame.f.get(self.frame_key,{}).keys()) for frame in frames ] # get all queues in all frames in clip queues = [] # queue for queue in list(frame.f.get(self.frame_key,{}).keys()) for frame in frames ] # get all queues in all frames in clip
for frame in frames: for frame in frames:
if frame is not None: if frame is not None:
for queue,command in frame.f.get(self.frame_key,{}).items(): for queue, command in frame.f.get(self.frame_key, {}).items():
queues.append(queue) queues.append(queue)
if command is not None and len(command)==2: if command is not None and len(command) == 2:
self.cmd_size[queue] = len(command[1]) self.cmd_size[queue] = len(command[1])
if command is not None and command[1] is not None: if command is not None and command[1] is not None:
last[queue] = command last[queue] = command
queues = list(set(queues)) queues = list(set(queues))
print ("got queues %s" % queues) print("got queues %s" % queues)
"""distance_cache = [{}]*len(frames) # list [ dict { queue: list [ distance to next arg args ] } ] """distance_cache = [{}]*len(frames) # list [ dict { queue: list [ distance to next arg args ] } ]
bob = {} bob = {}
@@ -322,88 +339,88 @@ class AutomationSourcePlugin(Plugin):
distance_cache[i-1] = bob""" distance_cache[i-1] = bob"""
def process(self, findex, frame): def process(self, findex, frame):
#for queue,command in enumerate(frame.f.get(self.frame_key,[])): # for queue,command in enumerate(frame.f.get(self.frame_key,[])):
data = frame.f.get(self.frame_key,None) data = frame.f.get(self.frame_key, None)
#if data is None: # if data is None:
# return # return
for queue in queues: for queue in queues:
if last.get(queue) is not None: if last.get(queue) is not None:
"""if data.get(queue) is not None: """if data.get(queue) is not None:
last[queue] = data.get(queue) last[queue] = data.get(queue)
continue""" continue"""
for argindex,value in enumerate(last.get(queue)[1]): for argindex, value in enumerate(last.get(queue)[1]):
#print ("findex %s: for argindex %s got last value %s" % (findex, argindex, value)) # print ("findex %s: for argindex %s got last value %s" % (findex, argindex, value))
#if data is not None: print ("data queue is %s" % data.get(queue,None)) # if data is not None: print ("data queue is %s" % data.get(queue,None))
if data is not None and data.get(queue,None) is not None and len(data.get(queue))>0 and len(data.get(queue)[1])>argindex and data.get(queue)[1][argindex] is not None: if data is not None and data.get(queue, None) is not None and len(data.get(queue)) > 0 and len(data.get(queue)[1]) > argindex and data.get(queue)[1][argindex] is not None:
last[queue][1][argindex] = data.get(queue)[1][argindex] last[queue][1][argindex] = data.get(queue)[1][argindex]
continue continue
gap,future_value = self.get_distance_value_command(frames,findex,queue,argindex) gap, future_value = self.get_distance_value_command(frames, findex, queue, argindex)
if gap==0 or future_value==value: if gap == 0 or future_value == value:
continue continue
#print("\tpassing %s and %s to interpolate" % (last[queue][argindex], future_value)) # print("\tpassing %s and %s to interpolate" % (last[queue][argindex], future_value))
newvalue = self.pc.fm.interpolate(last[queue][1][argindex], future_value, gap) newvalue = self.pc.fm.interpolate(last[queue][1][argindex], future_value, gap)
if data is None: if data is None:
frame.f[self.frame_key] = {} frame.f[self.frame_key] = {}
data = frame.f[self.frame_key] data = frame.f[self.frame_key]
if data.get(queue) is None: if data.get(queue) is None:
data[queue] = [last[queue][0], last[queue][1]]# [None]*self.cmd_size[queue]] data[queue] = [last[queue][0], last[queue][1]] # [None]*self.cmd_size[queue]]
#while len(data.get(queue)[1])<argindex: # while len(data.get(queue)[1])<argindex:
# data.get(queue)[1] += [] #.append(None) # data.get(queue)[1] += [] #.append(None)
data.get(queue)[1][argindex] = int(newvalue) data.get(queue)[1][argindex] = int(newvalue)
last[queue][1][argindex] = int(newvalue) last[queue][1][argindex] = int(newvalue)
elif data is not None and data.get(queue) is not None: elif data is not None and data.get(queue) is not None:
#print("no last[%s] already set, setting to %s" % (queue, data.get(queue))) # print("no last[%s] already set, setting to %s" % (queue, data.get(queue)))
last[queue] = data.get(queue) last[queue] = data.get(queue)
for i in range(1): for i in range(1):
for findex,frame in enumerate(frames): for findex, frame in enumerate(frames):
if frame is None: if frame is None:
continue continue
process(self,findex,frame) process(self, findex, frame)
print("\nAutomationSourcePlugin got interpolated clip: %s" % [ f.f for f in frames if f is not None ]) print("\nAutomationSourcePlugin got interpolated clip: %s" % [f.f for f in frames if f is not None])
self.distance_cache = {} self.distance_cache = {}
distance_cache = {} distance_cache = {}
def get_distance_value_command(self, frames, findex, queue, argindex): def get_distance_value_command(self, frames, findex, queue, argindex):
distance_cache = self.distance_cache distance_cache = self.distance_cache
# check if we have a cached value that is lower than the findex # check if we have a cached value that is lower than the findex
if distance_cache.get(queue) is not None and len(distance_cache.get(queue))>=(argindex+1) and distance_cache.get(queue)[argindex] is not None and distance_cache.get(queue)[argindex]['position'] >= findex: if distance_cache.get(queue) is not None and len(distance_cache.get(queue)) >= (argindex + 1) and distance_cache.get(queue)[argindex] is not None and distance_cache.get(queue)[argindex]['position'] >= findex:
position = distance_cache.get(queue)[argindex]['position'] position = distance_cache.get(queue)[argindex]['position']
#return len(frames)- # return len(frames)-
return abs(position-findex), distance_cache.get(queue)[argindex]['value'] return abs(position - findex), distance_cache.get(queue)[argindex]['value']
#print("\t\tget_distance_value_command(findex %s, queue %s, argindex %s)" %(findex,queue,argindex)) # print("\t\tget_distance_value_command(findex %s, queue %s, argindex %s)" %(findex,queue,argindex))
for i in range(1,len(frames)): for i in range(1, len(frames)):
search_findex = i + findex search_findex = i + findex
search_findex %= len(frames) search_findex %= len(frames)
if frames[search_findex] is None: if frames[search_findex] is None:
continue continue
#print("\t\t\tgetting frame index %s" % search_findex) # print("\t\t\tgetting frame index %s" % search_findex)
frame = frames[search_findex] frame = frames[search_findex]
data = frame.f.get(self.frame_key,None) data = frame.f.get(self.frame_key, None)
#print("\t\t\tgot frame data %s" % data) # print("\t\t\tgot frame data %s" % data)
if data is None: if data is None:
continue continue
command = data.get(queue,None) command = data.get(queue, None)
if command is None: if command is None:
continue continue
print("\t\t\tget_distance_value_command testing %s argindex %s - command looks like %s" % (queue, argindex, command)) print("\t\t\tget_distance_value_command testing %s argindex %s - command looks like %s" % (queue, argindex, command))
if len(command[1])>argindex: if len(command[1]) > argindex:
if command[1][argindex] is not None and findex!=i: if command[1][argindex] is not None and findex != i:
print("\t\t\t\t\tgot distance %s to value for argindex %s: %s" % (i, argindex, command[1][argindex])) print("\t\t\t\t\tgot distance %s to value for argindex %s: %s" % (i, argindex, command[1][argindex]))
if distance_cache.get(queue) is None: if distance_cache.get(queue) is None:
distance_cache[queue] = [None]*(self.cmd_size[queue]) distance_cache[queue] = [None] * (self.cmd_size[queue])
#while len(distance_cache[queue])<(argindex+1): # while len(distance_cache[queue])<(argindex+1):
# distance_cache[queue] += [None] # distance_cache[queue] += [None]
distance_cache[queue][argindex] = { 'position': i, 'value': command[1][argindex] } distance_cache[queue][argindex] = {'position': i, 'value': command[1][argindex]}
return i, 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: """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 i, frames[search_findex].f.get(self.frame_key,{}).get(queue,[])[argindex]"""
return 0, None return 0, None
@@ -416,6 +433,7 @@ 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
that contain a class definition that is inheriting from the Plugin class that contain a class definition that is inheriting from the Plugin class
""" """
@property @property
def display(self): def display(self):
return self.actions.display return self.actions.display
@@ -438,9 +456,9 @@ class PluginCollection(object):
""" """
self.plugin_package = plugin_package self.plugin_package = plugin_package
self.message_handler = message_handler self.message_handler = message_handler
#self.shaders = lambda: data.shaders # self.shaders = lambda: data.shaders
self.data = data self.data = data
#self.actions = message_handler.actions # self.actions = message_handler.actions
self.reload_plugins() self.reload_plugins()
# set up a FrameManager too so that plugins can use it # set up a FrameManager too so that plugins can use it
@@ -448,6 +466,7 @@ class PluginCollection(object):
def read_json(self, file_name): def read_json(self, file_name):
return self.data._read_plugin_json(file_name) return self.data._read_plugin_json(file_name)
def update_json(self, file_name, data): def update_json(self, file_name, data):
return self.data._update_plugin_json(file_name, data) return self.data._update_plugin_json(file_name, data)
@@ -464,7 +483,8 @@ class PluginCollection(object):
def quit_plugins(self): def quit_plugins(self):
# tell each plugin to quit # tell each plugin to quit
for plugin in self.get_plugins(): 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): def stop_plugin_name(self, name):
for plugin in self.get_plugins(include_disabled=True): for plugin in self.get_plugins(include_disabled=True):
@@ -472,15 +492,14 @@ class PluginCollection(object):
plugin.stop_plugin() plugin.stop_plugin()
def start_plugin_name(self, name): def start_plugin_name(self, name):
#print("start_plugin_name got %s"%name) # print("start_plugin_name got %s"%name)
for plugin in self.get_plugins(include_disabled=True): for plugin in self.get_plugins(include_disabled=True):
#print("looking for %s vs %s" % (type(plugin).__name__, name)) # print("looking for %s vs %s" % (type(plugin).__name__, name))
if type(plugin).__name__ == name: if type(plugin).__name__ == name:
#print("starting %s" %name) # print("starting %s" %name)
plugin.start_plugin() plugin.start_plugin()
def get_plugins(self, clazz=None, include_disabled=False):
def get_plugins(self, clazz = None, include_disabled = False):
if clazz: if clazz:
return [c for c in self.plugins if isinstance(c, clazz) and (include_disabled or not c.disabled)] return [c for c in self.plugins if isinstance(c, clazz) and (include_disabled or not c.disabled)]
else: else:
@@ -488,8 +507,8 @@ class PluginCollection(object):
def get_plugin_for_class_name(self, class_name): def get_plugin_for_class_name(self, class_name):
for plugin in self.get_plugins(): for plugin in self.get_plugins():
#print("got class name %s" % type(plugin).__name__==class_name) # print("got class name %s" % type(plugin).__name__==class_name)
if type(plugin).__name__==class_name == class_name: if type(plugin).__name__ == class_name == class_name:
return plugin return plugin
return None return None
@@ -505,12 +524,11 @@ 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 defined in this file # or one of the base classes defined in this file
ignore_list = [ Plugin, ActionsPlugin, SequencePlugin, MidiFeedbackPlugin, DisplayPlugin, ModulationReceiverPlugin, AutomationSourcePlugin ] 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))
# Now that we have looked at all the modules in the current package, start looking # Now that we have looked at all the modules in the current package, start looking
# recursively for additional modules in sub packages # recursively for additional modules in sub packages
# disabled 03-2020 to try and avoid problem with subclasses-of-subclasses being listed twice.. # 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: for child_pkg in child_pkgs:
self.walk_package(package + '.' + child_pkg)""" self.walk_package(package + '.' + child_pkg)"""
## helpers ## helpers
def get_variable(self, varname, default=0.0): def get_variable(self, varname, default=0.0):
from plugins.ManipulatePlugin import ManipulatePlugin from plugins.ManipulatePlugin import ManipulatePlugin

View File

@@ -9,7 +9,7 @@ class Display(object):
MENU_HEIGHT = 10 MENU_HEIGHT = 10
SELECTOR_WIDTH = 0.47 SELECTOR_WIDTH = 0.47
ROW_OFFSET = 6.0 ROW_OFFSET = 6.0
TITLES = ['{0} r_e_c_u_r {0}'.format('='*18), '{0} c_o_n_j_u_r {1}'.format('='*18, '='*16), '{0} d_e_t_o_u_r {1}'.format('='*18, '='*16)] TITLES = ['{0} r_e_c_u_r {0}'.format('=' * 18), '{0} c_o_n_j_u_r {1}'.format('=' * 18, '=' * 16), '{0} d_e_t_o_u_r {1}'.format('=' * 18, '=' * 16)]
def __init__(self, tk, video_driver, shaders, message_handler, data): def __init__(self, tk, video_driver, shaders, message_handler, data):
self.tk = tk self.tk = tk
@@ -51,7 +51,7 @@ class Display(object):
self._load_player() self._load_player()
self._load_display_body() self._load_display_body()
self._load_message() self._load_message()
#print('the number of tags are {}'.format(len(self.display_text.tag_names()))) # print('the number of tags are {}'.format(len(self.display_text.tag_names())))
self.display_text.pack() self.display_text.pack()
def _load_title(self): def _load_title(self):
@@ -107,7 +107,6 @@ class Display(object):
self.display_text.tag_add("DISPLAY_MODE", 4.19, 4.29) self.display_text.tag_add("DISPLAY_MODE", 4.19, 4.29)
self.display_text.tag_add("COLUMN_NAME", 5.0, 6.0) self.display_text.tag_add("COLUMN_NAME", 5.0, 6.0)
def _load_plugin_page(self, display_mode, plugin): def _load_plugin_page(self, display_mode, plugin):
plugin.show_plugin(self, display_mode) plugin.show_plugin(self, display_mode)
@@ -119,7 +118,7 @@ class Display(object):
self.display_text.insert(END, '{:>6} {:<17} {:>5} {:<5} {:<5} \n'.format( self.display_text.insert(END, '{:>6} {:<17} {:>5} {:<5} {:<5} \n'.format(
'{}-slot'.format(self.data.bank_number), 'name', 'length', 'start', 'end')) '{}-slot'.format(self.data.bank_number), 'name', 'length', 'start', 'end'))
for index, slot in enumerate(bank_data): for index, slot in enumerate(bank_data):
name_without_extension = slot['name'].rsplit('.',1)[0] name_without_extension = slot['name'].rsplit('.', 1)[0]
self.display_text.insert(END, '{:^6} {:<17} {:^5} {:>5} {:<5} \n'.format( self.display_text.insert(END, '{:^6} {:<17} {:^5} {:>5} {:<5} \n'.format(
index, name_without_extension[0:17], self.format_time_value(slot['length']), index, name_without_extension[0:17], self.format_time_value(slot['length']),
self.format_time_value(slot['start']), self.format_time_value(slot['end']))) self.format_time_value(slot['start']), self.format_time_value(slot['end'])))
@@ -134,7 +133,7 @@ class Display(object):
bank_slot = self.video_driver.next_player.bankslot_number bank_slot = self.video_driver.next_player.bankslot_number
else: else:
bank_slot = self.video_driver.current_player.bankslot_number bank_slot = self.video_driver.current_player.bankslot_number
current_bank , current_slot = self.data.split_bankslot_number(bank_slot) current_bank, current_slot = self.data.split_bankslot_number(bank_slot)
if current_bank is self.data.bank_number: if current_bank is self.data.bank_number:
self._highlight_this_row(current_slot) self._highlight_this_row(current_slot)
@@ -185,14 +184,14 @@ class Display(object):
self.display_text.insert(END, '{:<35} {:<8} \n'.format('plugin', 'status')) self.display_text.insert(END, '{:<35} {:<8} \n'.format('plugin', 'status'))
## showing list of plugins: ## showing list of plugins:
plugins_list = sorted([ plugins_list = sorted([
(type(plugin).__name__, type(plugin).__name__ in self.data.get_enabled_plugin_class_names())\ (type(plugin).__name__, type(plugin).__name__ in self.data.get_enabled_plugin_class_names()) \
for plugin in self.data.plugins.get_plugins(include_disabled=True) for plugin in self.data.plugins.get_plugins(include_disabled=True)
]) ])
self.plugins_menu.menu_list = plugins_list self.plugins_menu.menu_list = plugins_list
number_of_plugins = len(plugins_list) number_of_plugins = len(plugins_list)
for index in range(number_of_plugins): for index in range(number_of_plugins):
if line_count >= self.MENU_HEIGHT : if line_count >= self.MENU_HEIGHT:
break break
if index >= self.plugins_menu.top_menu_index: if index >= self.plugins_menu.top_menu_index:
plugin_line = plugins_list[index] plugin_line = plugins_list[index]
@@ -204,7 +203,6 @@ class Display(object):
self._highlight_this_row(self.plugins_menu.selected_list_index - self.plugins_menu.top_menu_index) self._highlight_this_row(self.plugins_menu.selected_list_index - self.plugins_menu.top_menu_index)
def _load_shaders(self): def _load_shaders(self):
line_count = 0 line_count = 0
self.display_text.insert(END, '{} \n'.format(self.body_title)) self.display_text.insert(END, '{} \n'.format(self.body_title))
@@ -214,20 +212,20 @@ class Display(object):
self.display_text.insert(END, '{:<1}{}{:<1}:{:<2} {:<16} '.format \ self.display_text.insert(END, '{:<1}{}{:<1}:{:<2} {:<16} '.format \
(self.data.shader_layer, (self.data.shader_layer,
self.get_speed_indicator(self.shaders.selected_speed_list[self.data.shader_layer]), self.get_speed_indicator(self.shaders.selected_speed_list[self.data.shader_layer]),
self.shaders.selected_status_list[self.data.shader_layer],shader['shad_type'][0], self.shaders.selected_status_list[self.data.shader_layer], shader['shad_type'][0],
shader['name'].lstrip()[0:16] )) shader['name'].lstrip()[0:16]))
for i in range(min(4,shader['param_number'])): for i in range(min(4, shader['param_number'])):
display_param = self.format_param_value(self.shaders.selected_param_list[self.data.shader_layer][i]) display_param = self.format_param_value(self.shaders.selected_param_list[self.data.shader_layer][i])
if display_param == 100: if display_param == 100:
display_param == 99 display_param == 99
self.display_text.insert(END, 'x{}:{:02d}'.format(i, display_param)) self.display_text.insert(END, 'x{}:{:02d}'.format(i, display_param))
self.display_text.insert(END,'\n') self.display_text.insert(END, '\n')
self.display_text.tag_add("COLUMN_NAME", 5.0, 6.0) self.display_text.tag_add("COLUMN_NAME", 5.0, 6.0)
## showing list of other shaders: ## showing list of other shaders:
shaders_list = self.shaders.shaders_menu_list shaders_list = self.shaders.shaders_menu_list
number_of_shader_items = len(shaders_list) number_of_shader_items = len(shaders_list)
for index in range(number_of_shader_items): for index in range(number_of_shader_items):
if line_count >= self.MENU_HEIGHT : if line_count >= self.MENU_HEIGHT:
break break
if index >= self.shaders.shaders_menu.top_menu_index: if index >= self.shaders.shaders_menu.top_menu_index:
shader_line = shaders_list[index] shader_line = shaders_list[index]
@@ -252,7 +250,7 @@ class Display(object):
shader = self.shaders.selected_shader_list[self.data.shader_layer] shader = self.shaders.selected_shader_list[self.data.shader_layer]
for i in range(min(4,shader['param_number'])): for i in range(min(4, shader['param_number'])):
display_param = self.format_param_value(self.shaders.selected_param_list[self.data.shader_layer][i]) display_param = self.format_param_value(self.shaders.selected_param_list[self.data.shader_layer][i])
if display_param == 100: if display_param == 100:
display_param == 99 display_param == 99
@@ -260,7 +258,7 @@ class Display(object):
self.display_text.insert(END, '\n') self.display_text.insert(END, '\n')
for index, slot in enumerate(shader_bank_data): for index, slot in enumerate(shader_bank_data):
name_without_extension = slot['name'].rsplit('.',1)[0] name_without_extension = slot['name'].rsplit('.', 1)[0]
self.display_text.insert(END, '{:^6} {:<17} {:<5} \n'.format(index, name_without_extension[0:17], slot['shad_type'])) self.display_text.insert(END, '{:^6} {:<17} {:<5} \n'.format(index, name_without_extension[0:17], slot['shad_type']))
if index % 2: if index % 2:
self.display_text.tag_add("ZEBRA_STRIPE", self.ROW_OFFSET + index, self.display_text.tag_add("ZEBRA_STRIPE", self.ROW_OFFSET + index,
@@ -314,8 +312,8 @@ class Display(object):
self._highlight_this_param(self.shaders.focused_param) """ self._highlight_this_param(self.shaders.focused_param) """
# show info about the modulation configuration # show info about the modulation configuration
#self.display_text.insert(END, "Lyr|1a b c d|2a b c d|3a b c d|4a b c d\n") # self.display_text.insert(END, "Lyr|1a b c d|2a b c d|3a b c d|4a b c d\n")
#self.display_text.insert(END, "Lyr") # self.display_text.insert(END, "Lyr")
"""for i in range(4): """for i in range(4):
self.display_text.insert(END, "|%s"%i) self.display_text.insert(END, "|%s"%i)
for i in range(4): for i in range(4):
@@ -323,7 +321,7 @@ class Display(object):
if i==self.shaders.selected_modulation_slot: if i==self.shaders.selected_modulation_slot:
a = a.upper() a = a.upper()
self.display_text.insert(END, "%s "%a)""" self.display_text.insert(END, "%s "%a)"""
#self.display_text.insert(END, "\n") # self.display_text.insert(END, "\n")
"""for layer, modulations in enumerate(self.shaders.modulation_level): """for layer, modulations in enumerate(self.shaders.modulation_level):
if (layer==self.data.shader_layer): if (layer==self.data.shader_layer):
self.display_text.insert(END, '*') self.display_text.insert(END, '*')
@@ -343,14 +341,14 @@ class Display(object):
o += "\n Modmatrix:\t" o += "\n Modmatrix:\t"
name = self.shaders.selected_shader_list[layer].get('name').strip() name = self.shaders.selected_shader_list[layer].get('name').strip()
#o = "" # o = ""
for slot in range(4): for slot in range(4):
sl = self.get_mod_slot_label(slot) sl = self.get_mod_slot_label(slot)
o+= sl + ("[" if sl.isupper() else "-") o += sl + ("[" if sl.isupper() else "-")
for param in range(4): for param in range(4):
o += self.get_bar(self.shaders.modulation_level[layer][param][slot]) o += self.get_bar(self.shaders.modulation_level[layer][param][slot])
o+= ("]" if sl.isupper() else "-") + " " o += ("]" if sl.isupper() else "-") + " "
self.display_text.insert(END, "%s %s:\t%s\n\n"%(">" if layer==self.data.shader_layer else " ", layer, o)) self.display_text.insert(END, "%s %s:\t%s\n\n" % (">" if layer == self.data.shader_layer else " ", layer, o))
self.display_text.insert(END, '\n') self.display_text.insert(END, '\n')
# todo: this doesnt work but would be a better way to highlight the selected modulation slot/layer # todo: this doesnt work but would be a better way to highlight the selected modulation slot/layer
"""self._highlight_this_param( """self._highlight_this_param(
@@ -360,12 +358,11 @@ class Display(object):
column_offset = 0.1 column_offset = 0.1
)""" )"""
def _load_detour(self): def _load_detour(self):
line_count = 0 line_count = 0
self.display_text.insert(END, '{} \n'.format(self.body_title)) self.display_text.insert(END, '{} \n'.format(self.body_title))
## showing current detour info: ## showing current detour info:
self.display_text.insert(END, '{:^23} {:^22} \n'.format('SETTING', 'VALUE')) self.display_text.insert(END, '{:^23} {:^22} \n'.format('SETTING', 'VALUE'))
self.display_text.insert(END, '{:>23} {:<22} \n'.format("DETOUR_ACTIVE", self.data.detour_active)) self.display_text.insert(END, '{:>23} {:<22} \n'.format("DETOUR_ACTIVE", self.data.detour_active))
for index, (key, value) in enumerate(self.data.detour_settings.items()): for index, (key, value) in enumerate(self.data.detour_settings.items()):
@@ -381,21 +378,21 @@ class Display(object):
self.display_text.insert(END, '{:5} {:42} \n'.format( self.display_text.insert(END, '{:5} {:42} \n'.format(
self.message_handler.current_message[0], self.message_handler.current_message[1][0:38])) self.message_handler.current_message[0], self.message_handler.current_message[1][0:38]))
self.display_text.tag_add('{}_MESSAGE'.format( self.display_text.tag_add('{}_MESSAGE'.format(
self.message_handler.current_message[0]), 16.0,16.0 + self.SELECTOR_WIDTH) self.message_handler.current_message[0]), 16.0, 16.0 + self.SELECTOR_WIDTH)
if self.message_handler.current_message[2]: if self.message_handler.current_message[2]:
self.message_handler.current_message[2] = False self.message_handler.current_message[2] = False
message_length = 4000 message_length = 4000
self.tk.after(message_length, self.message_handler.clear_message) self.tk.after(message_length, self.message_handler.clear_message)
elif self.data.function_on: elif self.data.function_on:
self.display_text.insert(END, '{:^47} \n'.format('< FUNCTION KEY ON >')) self.display_text.insert(END, '{:^47} \n'.format('< FUNCTION KEY ON >'))
self.display_text.tag_add('FUNCTION', 16.0,16.0 + self.SELECTOR_WIDTH) self.display_text.tag_add('FUNCTION', 16.0, 16.0 + self.SELECTOR_WIDTH)
else: else:
feedback = '' feedback = ''
if self.data.feedback_active: if self.data.feedback_active:
feedback = 'FDBCK' feedback = 'FDBCK'
self.display_text.insert(END, '{:8} {:<28} {:>5} \n'.format('CONTROL:', str(self.data.control_mode), feedback)) self.display_text.insert(END, '{:8} {:<28} {:>5} \n'.format('CONTROL:', str(self.data.control_mode), feedback))
self.display_text.tag_add('TITLE', 16.0,16.0 + self.SELECTOR_WIDTH) self.display_text.tag_add('TITLE', 16.0, 16.0 + self.SELECTOR_WIDTH)
def _highlight_this_row(self, row, gray=False): def _highlight_this_row(self, row, gray=False):
highlight_tag = "SELECT" highlight_tag = "SELECT"
@@ -410,12 +407,12 @@ class Display(object):
self.display_text.tag_remove("SELECT", self.ROW_OFFSET + row, self.display_text.tag_remove("SELECT", self.ROW_OFFSET + row,
self.ROW_OFFSET + self.SELECTOR_WIDTH + row) self.ROW_OFFSET + self.SELECTOR_WIDTH + row)
def _highlight_this_param(self, param_num, column_offset = 0.26, param_length = 0.05, param_row = None): def _highlight_this_param(self, param_num, column_offset=0.26, param_length=0.05, param_row=None):
if param_row is None: if param_row is None:
param_row = self.ROW_OFFSET - 1 param_row = self.ROW_OFFSET - 1
self.display_text.tag_add("SHADER_PARAM", self.display_text.tag_add("SHADER_PARAM",
round(param_row + column_offset + param_num*param_length,2), round(param_row + column_offset + param_num * param_length, 2),
round(param_row + column_offset + (param_num+1)*param_length, 2) round(param_row + column_offset + (param_num + 1) * param_length, 2)
) )
def _get_status_for_player(self): def _get_status_for_player(self):
@@ -428,10 +425,9 @@ class Display(object):
capture_status = '' capture_status = ''
preview_alpha = 0 preview_alpha = 0
if preview_alpha == None: if preview_alpha == None:
preview_alpha = 0 preview_alpha = 0
#print('capture alpha is {}'.format(preview_alpha)) # print('capture alpha is {}'.format(preview_alpha))
self._set_colour_from_alpha(now_alpha, preview_alpha, next_alpha) self._set_colour_from_alpha(now_alpha, preview_alpha, next_alpha)
@@ -440,7 +436,7 @@ class Display(object):
capture_info = '{}'.format(capture_status) capture_info = '{}'.format(capture_status)
return '{:17} {:10} {:17}'.format(now_info[:17], capture_info[:10], next_info[:18]) return '{:17} {:10} {:17}'.format(now_info[:17], capture_info[:10], next_info[:18])
def _get_banner_for_player(self,player): def _get_banner_for_player(self, player):
start, end, position = self.video_driver.get_player_info_for_banner(player) start, end, position = self.video_driver.get_player_info_for_banner(player)
banner = self.create_video_display_banner(start, end, position) banner = self.create_video_display_banner(start, end, position)
time_been = self.format_time_value(position - start) time_been = self.format_time_value(position - start)
@@ -455,13 +451,13 @@ class Display(object):
rec_time = self.capture.get_recording_time() rec_time = self.capture.get_recording_time()
capture_status = '' capture_status = ''
if is_previewing and is_recording == True: if is_previewing and is_recording == True:
capture_status = '<{}>'.format('REC'+ self.format_time_value(rec_time)) capture_status = '<{}>'.format('REC' + self.format_time_value(rec_time))
elif is_previewing and is_recording == 'saving': elif is_previewing and is_recording == 'saving':
capture_status = '<{}>'.format('_saving_') capture_status = '<{}>'.format('_saving_')
elif is_previewing: elif is_previewing:
capture_status = '<{}>'.format('_preview') capture_status = '<{}>'.format('_preview')
elif is_recording == True: elif is_recording == True:
capture_status = '[{}]'.format('REC'+ self.format_time_value(rec_time)) capture_status = '[{}]'.format('REC' + self.format_time_value(rec_time))
elif is_recording == 'saving': elif is_recording == 'saving':
capture_status = '[{}]'.format('_saving_') capture_status = '[{}]'.format('_saving_')
else: else:
@@ -469,14 +465,16 @@ class Display(object):
return capture_status return capture_status
def get_bar(self, value, max_value = 1.0): def get_bar(self, value, max_value=1.0):
if value is None: if value is None:
return " " return " "
value = abs(value / max_value) # abs() so negative values make some sense value = abs(value / max_value) # abs() so negative values make some sense
if value>1.0: value = 1.0 if value > 1.0:
elif value<0.0: value = 0.0 value = 1.0
elif value < 0.0:
value = 0.0
bar = u"_\u2581\u2582\u2583\u2584\u2585\u2586\u2587\u2588" bar = u"_\u2581\u2582\u2583\u2584\u2585\u2586\u2587\u2588"
g = '%s'%bar[int(value*(len(bar)-1))] g = '%s' % bar[int(value * (len(bar) - 1))]
return g return g
def get_mod_slot_label(self, slot): def get_mod_slot_label(self, slot):
@@ -485,22 +483,22 @@ class Display(object):
sl = sl.lower() sl = sl.lower()
return sl return sl
def get_speed_indicator(self, value, convert = True): def get_speed_indicator(self, value, convert=True):
if convert: if convert:
value = (value * 2.0) - 1.0 # convert 0 to 1 to -1 to +1 value = (value * 2.0) - 1.0 # convert 0 to 1 to -1 to +1
output = u"" output = u""
if value==0.0 or (value>=-0.02 and value<=0.02): if value == 0.0 or (value >= -0.02 and value <= 0.02):
output+=u"\u23f9" # stopped output += u"\u23f9" # stopped
elif value<=-0.5: elif value <= -0.5:
output+=u"\u00AB" # fast reverse output += u"\u00AB" # fast reverse
elif value<0.0: elif value < 0.0:
output+=u"\u2039" # reverse output += u"\u2039" # reverse
elif value>=0.5: elif value >= 0.5:
output+=u"\u00BB" # fast forward output += u"\u00BB" # fast forward
elif value>0.0: elif value > 0.0:
output+=u"\u203A" # forward output += u"\u203A" # forward
#output += " {:03f}".format(value) # output += " {:03f}".format(value)
output += self.get_bar(value) output += self.get_bar(value)
return output return output
@@ -508,12 +506,12 @@ class Display(object):
def get_compact_indicators(self, inp): def get_compact_indicators(self, inp):
step = 2 step = 2
s = "" s = ""
for i in range(0,len(inp),step): # number of shader slots per layer for i in range(0, len(inp), step): # number of shader slots per layer
selected1 = inp[i] selected1 = inp[i]
if i+1 > len(inp): # catch if odd number of elements passed to us? if i + 1 > len(inp): # catch if odd number of elements passed to us?
selected2 = False selected2 = False
else: else:
selected2 = inp[i+1] selected2 = inp[i + 1]
if selected1 and selected2: if selected1 and selected2:
# full block # full block
@@ -528,11 +526,9 @@ class Display(object):
# empty # empty
s += "_" s += "_"
#s += "#" if selected else "-" # s += "#" if selected else "-"
return s return s
@staticmethod @staticmethod
def create_video_display_banner(start, end, position): def create_video_display_banner(start, end, position):
banner_list = ['[', '-', '-', '-', '-', '-', '-', '-', '-', banner_list = ['[', '-', '-', '-', '-', '-', '-', '-', '-',
@@ -545,8 +541,8 @@ class Display(object):
banner_list[0] = '<' banner_list[0] = '<'
elif position > end: elif position > end:
banner_list[max] = '>' banner_list[max] = '>'
elif end - start != 0 and not math.isnan(position) : elif end - start != 0 and not math.isnan(position):
#print('start value is {}, end value is {}, position is {}'.format(start, end, position)) # print('start value is {}, end value is {}, position is {}'.format(start, end, position))
marker = int(math.floor(float(position - start) / marker = int(math.floor(float(position - start) /
float(end - start) * (max - 1)) + 1) float(end - start) * (max - 1)) + 1)
banner_list[marker] = '*' banner_list[marker] = '*'
@@ -564,7 +560,7 @@ class Display(object):
max = len(banner_list) - 1 max = len(banner_list) - 1
if size == 0: if size == 0:
size = max size = max
#print('start value is {}, end value is {}, position is {}'.format(start, end, position)) # print('start value is {}, end value is {}, position is {}'.format(start, end, position))
if start > 0: if start > 0:
start = int(math.floor(float(start) / start = int(math.floor(float(start) /
float(size) * (max - 1)) + 1) float(size) * (max - 1)) + 1)
@@ -591,13 +587,13 @@ class Display(object):
else: else:
is_recording = False is_recording = False
### scale values ### scale values
scaled_now = int(( now_alpha / 255 ) * (255 - upper_bound) + upper_bound) scaled_now = int((now_alpha / 255) * (255 - upper_bound) + upper_bound)
scaled_preview = int(( preview_alpha / 255 ) * (255 - upper_bound) + upper_bound) scaled_preview = int((preview_alpha / 255) * (255 - upper_bound) + upper_bound)
scaled_next = int(( next_alpha / 255 ) * (255 - upper_bound) + upper_bound) scaled_next = int((next_alpha / 255) * (255 - upper_bound) + upper_bound)
### convert to hex ### convert to hex
now_colour = self.hex_from_rgb(scaled_now, scaled_now, 0) now_colour = self.hex_from_rgb(scaled_now, scaled_now, 0)
capture_colour = self.hex_from_rgb(255 * is_recording, 100, scaled_preview ) capture_colour = self.hex_from_rgb(255 * is_recording, 100, scaled_preview)
next_colour = self.hex_from_rgb(0, scaled_next, scaled_next) next_colour = self.hex_from_rgb(0, scaled_next, scaled_next)
### update the colours ### update the colours
self.display_text.tag_configure("NOW_ALPHA", background="black", foreground=now_colour) self.display_text.tag_configure("NOW_ALPHA", background="black", foreground=now_colour)
@@ -617,14 +613,14 @@ class Display(object):
else: else:
selected_list.append('<{}>'.format(v[:2].lower())) selected_list.append('<{}>'.format(v[:2].lower()))
# 18 char to PURPLE : 18 - 29 ,18 after # 18 char to PURPLE : 18 - 29 ,18 after
if selected_list_index>4: if selected_list_index > 4:
selected_list = selected_list[selected_list_index-4:len(selected_list)] selected_list = selected_list[selected_list_index - 4:len(selected_list)]
selected_list = ['--'] + selected_list selected_list = ['--'] + selected_list
selected_string = ''.join(selected_list) selected_string = ''.join(selected_list)
#if len(selected_string)<19: # if len(selected_string)<19:
# selected_string += '-'*(21-len(selected_string)) # selected_string += '-'*(21-len(selected_string))
#selected_string = selected_string[:30] # selected_string = selected_string[:30]
#wid = 19 #int(2+((len(display_modes)/2)*4)) # wid = 19 #int(2+((len(display_modes)/2)*4))
output = ('-' * ((19) - (selected_list_index * 4))) + \ output = ('-' * ((19) - (selected_list_index * 4))) + \
selected_string + \ selected_string + \
('-' * (18 - ((len(display_modes) - selected_list_index - 1) * 4))) ('-' * (18 - ((len(display_modes) - selected_list_index - 1) * 4)))
@@ -641,11 +637,12 @@ class Display(object):
last_refreshed = 0 last_refreshed = 0
REFRESH_LIMIT = 100 REFRESH_LIMIT = 100
def refresh_display(self): def refresh_display(self):
if self.data.update_screen: if self.data.update_screen:
if time.time()*1000 - self.last_refreshed < self.REFRESH_LIMIT: if time.time() * 1000 - self.last_refreshed < self.REFRESH_LIMIT:
return return
self.last_refreshed = time.time()*1000 self.last_refreshed = time.time() * 1000
self.display_text.configure(state='normal') self.display_text.configure(state='normal')
self.display_text.delete(1.0, END) self.display_text.delete(1.0, END)
self._load_display() self._load_display()

View File

@@ -1,5 +1,6 @@
import os import os
class Menu(object): class Menu(object):
def __init__(self, data, message_handler, menu_height): def __init__(self, data, message_handler, menu_height):
self.data = data self.data = data
@@ -50,7 +51,6 @@ class Menu(object):
self.top_menu_index += self.menu_height self.top_menu_index += self.menu_height
self.selected_list_index = min(self.menu_height + self.selected_list_index, len(self.menu_list) - 1) self.selected_list_index = min(self.menu_height + self.selected_list_index, len(self.menu_list) - 1)
def update_open_folders(self, folder_name): def update_open_folders(self, folder_name):
if folder_name not in self.open_folders: if folder_name not in self.open_folders:
self.open_folders.append(folder_name) self.open_folders.append(folder_name)
@@ -72,6 +72,7 @@ class Menu(object):
else: else:
return True, dir_name.lstrip() return True, dir_name.lstrip()
class BrowserMenu(Menu): class BrowserMenu(Menu):
def __init__(self, data, message_handler, menu_height): def __init__(self, data, message_handler, menu_height):
Menu.__init__(self, data, message_handler, menu_height) Menu.__init__(self, data, message_handler, menu_height)
@@ -116,10 +117,9 @@ class BrowserMenu(Menu):
for slot_index, slot in enumerate(bank): for slot_index, slot in enumerate(bank):
print('&&&&&&&&&&&&', slot) print('&&&&&&&&&&&&', slot)
if file_name == slot['name']: if file_name == slot['name']:
return True, '{}-{}'.format(bank_index,slot_index) return True, '{}-{}'.format(bank_index, slot_index)
return False, '' return False, ''
def enter_on_browser_selection(self): def enter_on_browser_selection(self):
is_file, name = self.extract_file_type_and_name_from_menu_format( is_file, name = self.extract_file_type_and_name_from_menu_format(
self.menu_list[self.selected_list_index]['name']) self.menu_list[self.selected_list_index]['name'])
@@ -133,17 +133,16 @@ class BrowserMenu(Menu):
class SettingsMenu(Menu): class SettingsMenu(Menu):
FOLDER_ORDER = ['video', 'sampler', 'user_input', 'capture', 'shader', 'detour', 'system']
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']
SAMPLER_ORDER = ['LOOP_TYPE', 'LOAD_NEXT', 'RAND_START_MODE', 'RESET_PLAYERS', 'FIXED_LENGTH_MODE', 'FIXED_LENGTH', 'FIXED_LENGTH_MULTIPLY' ]
VIDEO_ORDER = ['VIDEOPLAYER_BACKEND'] VIDEO_ORDER = ['VIDEOPLAYER_BACKEND']
USER_INPUT_ORDER = ['MIDI_INPUT', 'MIDI_STATUS', 'CYCLE_MIDI_PORT', 'OSC_INPUT', 'ACCESS_POINT', 'REMOTE_SERVER', 'SHOW_IP' ] USER_INPUT_ORDER = ['MIDI_INPUT', 'MIDI_STATUS', 'CYCLE_MIDI_PORT', 'OSC_INPUT', 'ACCESS_POINT', 'REMOTE_SERVER', 'SHOW_IP']
CAPTURE_ORDER = ['DEVICE', 'TYPE'] CAPTURE_ORDER = ['DEVICE', 'TYPE']
SHADER_ORDER = ['USER_SHADER'] SHADER_ORDER = ['USER_SHADER']
DETOUR_ORDER = ['TRY_DEMO'] DETOUR_ORDER = ['TRY_DEMO']
SYSTEM_ORDER = [] SYSTEM_ORDER = []
SETTINGS_TO_HIDE = ['OUTPUT' ] SETTINGS_TO_HIDE = ['OUTPUT']
def __init__(self, data, message_handler, menu_height): def __init__(self, data, message_handler, menu_height):
@@ -159,7 +158,7 @@ class SettingsMenu(Menu):
if setting_folder_key in self.open_folders: if setting_folder_key in self.open_folders:
self.menu_list.append(dict(name='{}/'.format(setting_folder_key), value='')) self.menu_list.append(dict(name='{}/'.format(setting_folder_key), value=''))
order_list_name = '{}_ORDER'.format(setting_folder_key.upper()) order_list_name = '{}_ORDER'.format(setting_folder_key.upper())
ordered_value = self.order_keys_from_list(setting_folder_item, getattr(self,order_list_name)) ordered_value = self.order_keys_from_list(setting_folder_item, getattr(self, order_list_name))
for (setting_details_key, setting_details_item) in ordered_value: for (setting_details_key, setting_details_item) in ordered_value:
if not setting_details_key in self.SETTINGS_TO_HIDE: if not setting_details_key in self.SETTINGS_TO_HIDE:
self.menu_list.append(dict(name=' {}'.format(setting_details_key), value=self.data.make_empty_if_none(setting_details_item['value']))) self.menu_list.append(dict(name=' {}'.format(setting_details_key), value=self.data.make_empty_if_none(setting_details_item['value'])))
@@ -219,8 +218,8 @@ class ShadersMenu(Menu):
def __init__(self, data, message_handler, menu_height): def __init__(self, data, message_handler, menu_height):
Menu.__init__(self, data, message_handler, menu_height) Menu.__init__(self, data, message_handler, menu_height)
#self.top_menu_index = 1 # self.top_menu_index = 1
#self.selected_list_index = 1 # self.selected_list_index = 1
def generate_raw_shaders_list(self): def generate_raw_shaders_list(self):
######## starts the recursive process of listing all folders and shader files to display ######## ######## starts the recursive process of listing all folders and shader files to display ########
@@ -229,7 +228,6 @@ class ShadersMenu(Menu):
self._add_folder_to_shaders_list(path, 0) self._add_folder_to_shaders_list(path, 0)
return self.menu_list return self.menu_list
def _add_folder_to_shaders_list(self, current_path, current_level): 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 ######## ######## 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) split_name = os.path.splitext(f)
if (split_name[1].lower() in ['.frag', '.shader', '.glsl', '.glslf', '.fsh']): if (split_name[1].lower() in ['.frag', '.shader', '.glsl', '.glslf', '.fsh']):
self.menu_list.append(dict(name='{}{}'.format(indent, f), is_shader=True)) self.menu_list.append(dict(name='{}{}'.format(indent, f), is_shader=True))

View File

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

View File

@@ -12,8 +12,9 @@ def setup_osc_client(ip, port):
return udp_client.SimpleUDPClient(client_args.ip, client_args.port) return udp_client.SimpleUDPClient(client_args.ip, client_args.port)
client = setup_osc_client('127.0.0.1',5433)
client = setup_osc_client('127.0.0.1', 5433)
client.send_message("/shutdown", True) client.send_message("/shutdown", True)
client = setup_osc_client('127.0.0.1',9000) client = setup_osc_client('127.0.0.1', 9000)
client.send_message("/shutdown", True) client.send_message("/shutdown", True)

View File

@@ -3,8 +3,7 @@ import math
from data_centre.plugin_collection import ActionsPlugin, AutomationSourcePlugin, DisplayPlugin, SequencePlugin from data_centre.plugin_collection import ActionsPlugin, AutomationSourcePlugin, DisplayPlugin, SequencePlugin
class LFOModulationPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin, AutomationSourcePlugin): class LFOModulationPlugin(ActionsPlugin, SequencePlugin, DisplayPlugin, AutomationSourcePlugin):
MAX_LFOS = 4 MAX_LFOS = 4
PRESET_FILE_NAME = "LFOModulationPlugin/config.json" PRESET_FILE_NAME = "LFOModulationPlugin/config.json"
@@ -16,7 +15,7 @@ class LFOModulationPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin, Automation
selected_lfo = 0 selected_lfo = 0
# for keeping track of LFO levels # for keeping track of LFO levels
level = [0.0]*MAX_LFOS level = [0.0] * MAX_LFOS
speed = 0.5 speed = 0.5
# TODO: enable assigning of LFOs to mod slots # TODO: enable assigning of LFOs to mod slots
@@ -26,12 +25,13 @@ class LFOModulationPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin, Automation
stop_flag = False stop_flag = False
pause_flag = False pause_flag = False
def __init__(self, plugin_collection): def __init__(self, plugin_collection):
super().__init__(plugin_collection) super().__init__(plugin_collection)
#self.PRESET_FILE_NAME = "ShaderLoopRecordPlugin/frames.json" # self.PRESET_FILE_NAME = "ShaderLoopRecordPlugin/frames.json"
self.presets = self.load_presets() self.presets = self.load_presets()
self.level = self.presets.get('levels', [0.0]*self.MAX_LFOS).copy() self.level = self.presets.get('levels', [0.0] * self.MAX_LFOS).copy()
self.active = self.presets.get('active', False) self.active = self.presets.get('active', False)
self.set_lfo_speed_direct(self.presets.get('speed', self.speed)) self.set_lfo_speed_direct(self.presets.get('speed', self.speed))
@@ -47,30 +47,30 @@ class LFOModulationPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin, Automation
def load_presets(self): def load_presets(self):
print("trying load presets? %s " % self.PRESET_FILE_NAME) print("trying load presets? %s " % self.PRESET_FILE_NAME)
return self.pc.read_json(self.PRESET_FILE_NAME) or { 'levels': [0.0]*self.MAX_LFOS, 'active': self.active } return self.pc.read_json(self.PRESET_FILE_NAME) or {'levels': [0.0] * self.MAX_LFOS, 'active': self.active}
def save_presets(self): def save_presets(self):
#for cmd,struct in self.commands.items(): # for cmd,struct in self.commands.items():
# self.presets.setdefault('modulation_levels',{})[cmd] = struct.get('modulation',[{},{},{},{}]) # self.presets.setdefault('modulation_levels',{})[cmd] = struct.get('modulation',[{},{},{},{}])
self.pc.update_json(self.PRESET_FILE_NAME, { 'levels': self.level.copy(), 'active': self.active, 'speed': self.speed } ) self.pc.update_json(self.PRESET_FILE_NAME, {'levels': self.level.copy(), 'active': self.active, 'speed': self.speed})
# DisplayPlugin methods # DisplayPlugin methods
def get_display_modes(self): def get_display_modes(self):
return ['LFOMODU','NAV_LFO'] return ['LFOMODU', 'NAV_LFO']
def show_plugin(self, display, display_mode): def show_plugin(self, display, display_mode):
from tkinter import END from tkinter import END
#super(DisplayPlugin).show_plugin(display, display_mode) # super(DisplayPlugin).show_plugin(display, display_mode)
display.display_text.insert(END, '{} \n'.format(display.body_title)) display.display_text.insert(END, '{} \n'.format(display.body_title))
display.display_text.insert(END, "LFOModulation is ") display.display_text.insert(END, "LFOModulation is ")
display.display_text.insert(END, "ACTIVE" if self.active else "not active") display.display_text.insert(END, "ACTIVE" if self.active else "not active")
display.display_text.insert(END, "\tSpeed: {:4.1f}% {}\n\n".format(self.speed*100, display.get_speed_indicator(self.speed/2.0, convert=False))) display.display_text.insert(END, "\tSpeed: {:4.1f}% {}\n\n".format(self.speed * 100, display.get_speed_indicator(self.speed / 2.0, convert=False)))
for lfo,value in enumerate(self.level): for lfo, value in enumerate(self.level):
display.display_text.insert(END, "*" if self.selected_lfo==lfo else " ") display.display_text.insert(END, "*" if self.selected_lfo == lfo else " ")
display.display_text.insert(END, "lfo {} level: {:4.2f}% {}\t".format(lfo,value*100,display.get_bar(value))) display.display_text.insert(END, "lfo {} level: {:4.2f}% {}\t".format(lfo, value * 100, display.get_bar(value)))
display.display_text.insert(END, "{}\t{}\n".format(self.last_lfo_status[lfo], display.get_bar(self.last_lfo_value[lfo]))) display.display_text.insert(END, "{}\t{}\n".format(self.last_lfo_status[lfo], display.get_bar(self.last_lfo_value[lfo])))
display.display_text.insert(END, "\tslot %s\t%s\n" % (display.get_mod_slot_label(lfo), self.formula[lfo])) display.display_text.insert(END, "\tslot %s\t%s\n" % (display.get_mod_slot_label(lfo), self.formula[lfo]))
@@ -80,9 +80,9 @@ class LFOModulationPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin, Automation
# methods/vars for AutomationSourcePlugin # methods/vars for AutomationSourcePlugin
# a lot of the nitty-gritty handled in parent class, these are for interfacing to the plugin # a lot of the nitty-gritty handled in parent class, these are for interfacing to the plugin
def get_frame_data(self): def get_frame_data(self):
diff = { 'levels': self.level.copy(), 'speed': self.speed, 'active': self.active } diff = {'levels': self.level.copy(), 'speed': self.speed, 'active': self.active}
#self.last_record = {} # self.last_record = {}
#print(">>> reporting frame data for rec\n\t%s" % diff) # print(">>> reporting frame data for rec\n\t%s" % diff)
return diff return diff
def recall_frame_data(self, data): def recall_frame_data(self, data):
@@ -90,7 +90,7 @@ class LFOModulationPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin, Automation
return return
# print(">>>>recall from data:\n\t%s\n" %data) # print(">>>>recall from data:\n\t%s\n" %data)
if data.get('levels') is not None: if data.get('levels') is not None:
for slot,level in enumerate(data.get('levels')): for slot, level in enumerate(data.get('levels')):
self.set_lfo_modulation_level(slot, level) self.set_lfo_modulation_level(slot, level)
if data.get('active') is not None: if data.get('active') is not None:
self.active = data.get('active') self.active = data.get('active')
@@ -108,41 +108,43 @@ class LFOModulationPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin, Automation
line += "active " if data.get('active') else 'inactive ' line += "active " if data.get('active') else 'inactive '
if data.get('speed') is not None: if data.get('speed') is not None:
line += self.pc.display.get_speed_indicator(data.get('speed')) line += self.pc.display.get_speed_indicator(data.get('speed'))
#print ("returning %s from %s" %(line, data)) # print ("returning %s from %s" %(line, data))
return line return line
# ActionsPlugin methods # ActionsPlugin methods
@property @property
def parserlist(self): def parserlist(self):
return [ return [
( r"^set_lfo_modulation_([0-3])_level$", self.set_lfo_modulation_level ), (r"^set_lfo_modulation_([0-3])_level$", self.set_lfo_modulation_level),
( r"^toggle_lfo_active$", self.toggle_lfo_active ), (r"^toggle_lfo_active$", self.toggle_lfo_active),
( r"^set_lfo_speed", self.set_lfo_speed ), (r"^set_lfo_speed", self.set_lfo_speed),
( r"^select_lfo$", self.select_lfo ), (r"^select_lfo$", self.select_lfo),
( r"^select_previous_lfo$", self.select_previous_lfo ), (r"^select_previous_lfo$", self.select_previous_lfo),
( r"^select_next_lfo$", self.select_next_lfo ), (r"^select_next_lfo$", self.select_next_lfo),
( r"^increase_lfo_([0-3])_level$", self.increase_lfo_level ), (r"^increase_lfo_([0-3])_level$", self.increase_lfo_level),
( r"^decrease_lfo_([0-3])_level$", self.decrease_lfo_level ), (r"^decrease_lfo_([0-3])_level$", self.decrease_lfo_level),
( r"^increase_selected_lfo_level$", self.increase_selected_lfo_level ), (r"^increase_selected_lfo_level$", self.increase_selected_lfo_level),
( r"^decrease_selected_lfo_level$", self.decrease_selected_lfo_level ), (r"^decrease_selected_lfo_level$", self.decrease_selected_lfo_level),
( r"^increase_lfo_speed", self.increase_lfo_speed ), (r"^increase_lfo_speed", self.increase_lfo_speed),
( r"^decrease_lfo_speed", self.decrease_lfo_speed ), (r"^decrease_lfo_speed", self.decrease_lfo_speed),
# TODO: changing formulas and LFO modes # TODO: changing formulas and LFO modes
] ]
def set_lfo_modulation_level(self, slot, value): def set_lfo_modulation_level(self, slot, value):
if (value<0.0): value = 0.0 if (value < 0.0):
if (value>1.0): value = 1.0 value = 0.0
if (value > 1.0):
value = 1.0
self.level[slot] = value self.level[slot] = value
def set_lfo_speed(self, speed): def set_lfo_speed(self, speed):
self.set_lfo_speed_direct(-4*(0.5-(speed))) self.set_lfo_speed_direct(-4 * (0.5 - (speed)))
def set_lfo_speed_direct(self, speed): def set_lfo_speed_direct(self, speed):
self.speed = speed self.speed = speed
if self.speed<-2.0: if self.speed < -2.0:
self.speed = -2.0 self.speed = -2.0
if self.speed>2.0: if self.speed > 2.0:
self.speed = 2.0 self.speed = 2.0
def toggle_lfo_active(self): def toggle_lfo_active(self):
@@ -151,35 +153,41 @@ class LFOModulationPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin, Automation
def select_lfo(self, lfo): def select_lfo(self, lfo):
self.selected_lfo = lfo self.selected_lfo = lfo
if self.selected_lfo>=self.MAX_LFOS: if self.selected_lfo >= self.MAX_LFOS:
self.selected_lfo = 0 self.selected_lfo = 0
if self.selected_lfo<0: if self.selected_lfo < 0:
self.selected_lfo = self.MAX_LFOS-1 self.selected_lfo = self.MAX_LFOS - 1
def select_next_lfo(self): def select_next_lfo(self):
self.select_lfo(self.selected_lfo+1) self.select_lfo(self.selected_lfo + 1)
def select_previous_lfo(self): def select_previous_lfo(self):
self.select_lfo(self.selected_lfo-1) self.select_lfo(self.selected_lfo - 1)
level_step = 0.125 level_step = 0.125
def increase_lfo_level(self, slot): def increase_lfo_level(self, slot):
self.set_lfo_modulation_level(slot, self.level[slot] + self.level_step) self.set_lfo_modulation_level(slot, self.level[slot] + self.level_step)
def decrease_lfo_level(self, slot): def decrease_lfo_level(self, slot):
self.set_lfo_modulation_level(slot, self.level[slot] - self.level_step) self.set_lfo_modulation_level(slot, self.level[slot] - self.level_step)
def increase_selected_lfo_level(self): def increase_selected_lfo_level(self):
self.increase_lfo_level(self.selected_lfo) self.increase_lfo_level(self.selected_lfo)
def decrease_selected_lfo_level(self): def decrease_selected_lfo_level(self):
self.decrease_lfo_level(self.selected_lfo) self.decrease_lfo_level(self.selected_lfo)
lfo_step = 0.25 lfo_step = 0.25
def increase_lfo_speed(self): def increase_lfo_speed(self):
self.set_lfo_speed_direct ( self.speed + self.lfo_step ) 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 if self.speed == 0.0: # dont rest on 0 - set to a small amount forward
self.speed = 0.05 self.speed = 0.05
def decrease_lfo_speed(self): def decrease_lfo_speed(self):
self.set_lfo_speed_direct ( self.speed - self.lfo_step ) 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 if self.speed == 0.0: # dont rest on 0 - set to a small amount forward
self.speed = -0.05 self.speed = -0.05
# Formula handling for generating automation # Formula handling for generating automation
@@ -189,25 +197,26 @@ class LFOModulationPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin, Automation
"f_sin", "f_sin",
"f_double_cos", "f_double_cos",
"f_invert_sin", "f_invert_sin",
#"f_invert_double_cos", # "f_invert_double_cos",
"f_linear" "f_linear"
] ]
# run the formula for the stored lfo configuration # run the formula for the stored lfo configuration
last_lfo_status = [None]*MAX_LFOS # for displaying status last_lfo_status = [None] * MAX_LFOS # for displaying status
last_lfo_value = [None]*MAX_LFOS last_lfo_value = [None] * MAX_LFOS
#lfo_speed = [1.0]*MAX_LFOS
# lfo_speed = [1.0]*MAX_LFOS
def getLFO(self, position, lfo): def getLFO(self, position, lfo):
lfo_value = getattr(self,self.formula[lfo])(position, self.level[lfo]) lfo_value = getattr(self, self.formula[lfo])(position, self.level[lfo])
self.last_lfo_value[lfo] = lfo_value self.last_lfo_value[lfo] = lfo_value
self.last_lfo_status[lfo] = "sent {:03.1f}%".format(lfo_value*100.0) self.last_lfo_status[lfo] = "sent {:03.1f}%".format(lfo_value * 100.0)
return lfo_value return lfo_value
# built-in waveshapes # built-in waveshapes
# outgoing values should be between 0 and 1!! # outgoing values should be between 0 and 1!!
# todo: more of the these, and better! # todo: more of the these, and better!
def f_sin(self, position, level): def f_sin(self, position, level):
#return level * (( math.sin(position*math.pi))) # return level * (( math.sin(position*math.pi)))
value = math.sin(position * math.pi * 2) / 2 value = math.sin(position * math.pi * 2) / 2
value *= level value *= level
value += 0.5 # normalise to range 0 - 1 value += 0.5 # normalise to range 0 - 1
@@ -218,7 +227,7 @@ class LFOModulationPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin, Automation
return 1.0 - self.f_sin(position, level) return 1.0 - self.f_sin(position, level)
def f_double_cos(self, position, level): def f_double_cos(self, position, level):
return self.f_sin(math.cos(position*math.pi), level) return self.f_sin(math.cos(position * math.pi), level)
def f_invert_double_cos(self, position, level): def f_invert_double_cos(self, position, level):
return 1.0 - self.f_double_cos(position, level) return 1.0 - self.f_double_cos(position, level)
@@ -237,10 +246,10 @@ class LFOModulationPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin, Automation
if not self.active: # output is disabled if not self.active: # output is disabled
return return
for lfo in range(0,self.MAX_LFOS): for lfo in range(0, self.MAX_LFOS):
# TODO: this is where would use assignable amounts and average across multiple inputs # TODO: this is where would use assignable amounts and average across multiple inputs
if self.level[lfo]>0.0: if self.level[lfo] > 0.0:
self.pc.actions.call_method_name( self.pc.actions.call_method_name(
"modulate_param_%s_to_amount_continuous"%lfo, "modulate_param_%s_to_amount_continuous" % lfo,
self.getLFO(position, lfo) self.getLFO(position, lfo)
) )

View File

@@ -1,5 +1,6 @@
from data_centre.plugin_collection import ActionsPlugin, DisplayPlugin, ModulationReceiverPlugin#, SequencePlugin from data_centre.plugin_collection import ActionsPlugin, DisplayPlugin, ModulationReceiverPlugin # , SequencePlugin
#import math
# import math
""" """
add to midi or osc mapping add to midi or osc mapping
@@ -39,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 DEBUG = False
def __init__(self, plugin_collection): def __init__(self, plugin_collection):
@@ -50,30 +51,31 @@ class ManipulatePlugin(ActionsPlugin,DisplayPlugin,ModulationReceiverPlugin):
@property @property
def parserlist(self): def parserlist(self):
return [ return [
( r"(.*)&&(.*)", self.run_multi ), # split && first since they need to be processed separately (r"(.*)&&(.*)", self.run_multi), # split && first since they need to be processed separately
( r"^invert\|(.*)$", self.invert ), (r"^invert\|(.*)$", self.invert),
( r"^f:(.*):\|(.*)$", self.formula ), # formula eg ```f:sin(x):|``` (r"^f:(.*):\|(.*)$", self.formula), # formula eg ```f:sin(x):|```
( r"^set_variable_([a-zA-Z0-9]+)$", self.set_variable ), (r"^set_variable_([a-zA-Z0-9]+)$", self.set_variable),
( r"^([A-Z0-9]+)>(.*)$", self.recall_variable ), # recall variable and pipe into righthand side eg ```VAR1>invert|set_the_shader_.....``` (r"^([A-Z0-9]+)>(.*)$", self.recall_variable), # recall variable and pipe into righthand side eg ```VAR1>invert|set_the_shader_.....```
( r"^(.*)>\&(.*)$", self.run_multi ), # pick up piped commands that duplicate a chain of values last (r"^(.*)>\&(.*)$", self.run_multi), # pick up piped commands that duplicate a chain of values last
] ]
# DisplayPlugin methods # DisplayPlugin methods
def show_plugin(self, display, display_mode): def show_plugin(self, display, display_mode):
from tkinter import END from tkinter import END
#super(DisplayPlugin).show_plugin(display, display_mode) # super(DisplayPlugin).show_plugin(display, display_mode)
display.display_text.insert(END, '{} \n'.format(display.body_title)) display.display_text.insert(END, '{} \n'.format(display.body_title))
display.display_text.insert(END, "test from ManipulatePlugin!\n") display.display_text.insert(END, "test from ManipulatePlugin!\n")
for key,value in self.variables.items(): for key, value in self.variables.items():
display.display_text.insert(END, "\t" + key + "\t{:03.2f}\n".format(value)) display.display_text.insert(END, "\t" + key + "\t{:03.2f}\n".format(value))
def get_display_modes(self): def get_display_modes(self):
return ["MANIPULA","NAV_MANI"] #"NAV_MANIPULATE"] return ["MANIPULA", "NAV_MANI"] # "NAV_MANIPULATE"]
# Actions # Actions
def run_multi(self, action1, action2, value): 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(action1, value)
self.pc.actions.call_method_name(action2, value) self.pc.actions.call_method_name(action2, value)
@@ -89,16 +91,19 @@ class ManipulatePlugin(ActionsPlugin,DisplayPlugin,ModulationReceiverPlugin):
def formula(self, formula, action, value): def formula(self, formula, action, value):
self.variables['x'] = 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) 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( self.pc.actions.call_method_name(
action, value action, value
) )
def set_variable(self, var_name, 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 self.variables[var_name] = value
def get_variable(self, var_name, default): def get_variable(self, var_name, default):
@@ -108,16 +113,16 @@ class ManipulatePlugin(ActionsPlugin,DisplayPlugin,ModulationReceiverPlugin):
return default return default
def recall_variable(self, var_name, action, *args): 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( self.pc.actions.call_method_name(
action, self.variables.get(var_name)# + list(args) action, self.variables.get(var_name) # + list(args)
) )
# ModulationReceiverPlugin methods # ModulationReceiverPlugin methods
# methods for ModulationReceiverPlugin - receives changes to the in-built modulation levels (-1 to +1) # methods for ModulationReceiverPlugin - receives changes to the in-built modulation levels (-1 to +1)
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
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) self.set_variable("MODVALUE%s" % ('ABCD'[param]), value)

View File

@@ -4,7 +4,7 @@ from data_centre.plugin_collection import MidiFeedbackPlugin
class MidiFeedbackAPCKey25Plugin(MidiFeedbackPlugin): class MidiFeedbackAPCKey25Plugin(MidiFeedbackPlugin):
#disabled = False # disabled = False
status = {} status = {}
@@ -12,12 +12,12 @@ class MidiFeedbackAPCKey25Plugin(MidiFeedbackPlugin):
super().__init__(plugin_collection) super().__init__(plugin_collection)
self.description = 'Outputs feedback to APC Key 25' self.description = 'Outputs feedback to APC Key 25'
def get_note(self,action,default): def get_note(self, action, default):
bind = self.pc.midi_input.find_binding_for_action(action) bind = self.pc.midi_input.find_binding_for_action(action)
if bind is not None and 'note_on' in bind: if bind is not None and 'note_on' in bind:
return int(bind.split(' ')[1]) return int(bind.split(' ')[1])
else: else:
print ("bind is %s, returning default" % bind) print("bind is %s, returning default" % bind)
return default return default
def stop_plugin(self): def stop_plugin(self):
@@ -33,15 +33,15 @@ class MidiFeedbackAPCKey25Plugin(MidiFeedbackPlugin):
self.init_notes() self.init_notes()
def init_notes(self): def init_notes(self):
self.NOTE_PLAY_SHADER = self.get_note('play_shader_0_0',32) self.NOTE_PLAY_SHADER = self.get_note('play_shader_0_0', 32)
self.NOTE_SHADER_FEEDBACK = self.get_note('toggle_feedback',85) self.NOTE_SHADER_FEEDBACK = self.get_note('toggle_feedback', 85)
self.NOTE_SCENE_LAUNCH_COLUMN = self.get_note('toggle_shader_layer_0',82) self.NOTE_SCENE_LAUNCH_COLUMN = self.get_note('toggle_shader_layer_0', 82)
self.NOTE_MODULATION_COLUMN = self.get_note('select_shader_modulation_slot_0', self.NOTE_SCENE_LAUNCH_COLUMN) self.NOTE_MODULATION_COLUMN = self.get_note('select_shader_modulation_slot_0', self.NOTE_SCENE_LAUNCH_COLUMN)
self.NOTE_CAPTURE_PREVIEW = self.get_note('toggle_capture_preview', 86) self.NOTE_CAPTURE_PREVIEW = self.get_note('toggle_capture_preview', 86)
self.NOTE_CLIP_STATUS_ROW = self.get_note('toggle_automation_clip_0', 8) self.NOTE_CLIP_STATUS_ROW = self.get_note('toggle_automation_clip_0', 8)
self.NOTE_SHADER_PRESET_ROW = self.get_note('select_preset_0', 0) self.NOTE_SHADER_PRESET_ROW = self.get_note('select_preset_0', 0)
self.NOTE_SHADER_LAYER_ON = [ #82, 83, 84 self.NOTE_SHADER_LAYER_ON = [ # 82, 83, 84
self.get_note('toggle_shader_layer_%i'%i, 82+i) for i in range(0,3) self.get_note('toggle_shader_layer_%i' % i, 82 + i) for i in range(0, 3)
] ]
def supports_midi_feedback(self, device_name): def supports_midi_feedback(self, device_name):
@@ -56,10 +56,10 @@ class MidiFeedbackAPCKey25Plugin(MidiFeedbackPlugin):
'note': note, 'note': note,
'velocity': velocity 'velocity': velocity
} }
#print("set status to %s: %s" % (note, self.status[note])) # print("set status to %s: %s" % (note, self.status[note]))
def send_command(self, command='note_on', note=None, velocity=None): def send_command(self, command='note_on', note=None, velocity=None):
#print("send_command(%s, %s)" % (note, velocity)) # print("send_command(%s, %s)" % (note, velocity))
self.midi_feedback_device.send( self.midi_feedback_device.send(
mido.Message(command, note=note, velocity=velocity) mido.Message(command, note=note, velocity=velocity)
) )
@@ -71,11 +71,12 @@ class MidiFeedbackAPCKey25Plugin(MidiFeedbackPlugin):
self.set_status(note=self.NOTE_CAPTURE_PREVIEW, velocity=int(on)) self.set_status(note=self.NOTE_CAPTURE_PREVIEW, velocity=int(on))
def feedback_shader_on(self, layer, slot, colour=None): def feedback_shader_on(self, layer, slot, colour=None):
if colour is None: colour = self.COLOUR_GREEN if colour is None:
self.set_status(note=(self.NOTE_PLAY_SHADER-(layer)*8)+slot, velocity=int(colour)) 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): def feedback_shader_off(self, layer, slot):
self.set_status(note=(self.NOTE_PLAY_SHADER-(layer)*8)+slot, velocity=self.COLOUR_OFF) self.set_status(note=(self.NOTE_PLAY_SHADER - (layer) * 8) + slot, velocity=self.COLOUR_OFF)
def feedback_shader_layer_on(self, layer): def feedback_shader_layer_on(self, layer):
self.set_status(note=self.NOTE_SHADER_LAYER_ON[layer], velocity=self.COLOUR_GREEN) self.set_status(note=self.NOTE_SHADER_LAYER_ON[layer], velocity=self.COLOUR_GREEN)
@@ -87,8 +88,8 @@ class MidiFeedbackAPCKey25Plugin(MidiFeedbackPlugin):
self.set_status(note=70, velocity=layer) self.set_status(note=70, velocity=layer)
def feedback_show_modulation(self, slot): def feedback_show_modulation(self, slot):
for i in range(self.NOTE_MODULATION_COLUMN,self.NOTE_MODULATION_COLUMN+4): for i in range(self.NOTE_MODULATION_COLUMN, self.NOTE_MODULATION_COLUMN + 4):
if slot==i-self.NOTE_MODULATION_COLUMN: if slot == i - self.NOTE_MODULATION_COLUMN:
self.set_status(note=i, velocity=self.COLOUR_GREEN) self.set_status(note=i, velocity=self.COLOUR_GREEN)
else: else:
self.set_status(note=i, velocity=self.COLOUR_OFF) self.set_status(note=i, velocity=self.COLOUR_OFF)
@@ -104,7 +105,7 @@ class MidiFeedbackAPCKey25Plugin(MidiFeedbackPlugin):
NOTE_PLAY_STATUS = 65 NOTE_PLAY_STATUS = 65
NOTE_RECORD_STATUS = 66 NOTE_RECORD_STATUS = 66
NOTE_OVERDUB_STATUS = 67 NOTE_OVERDUB_STATUS = 67
#NOTE_CLIP_STATUS_ROW = 8 # NOTE_CLIP_STATUS_ROW = 8
colour = self.COLOUR_OFF colour = self.COLOUR_OFF
if plugin.is_playing(): if plugin.is_playing():
@@ -133,13 +134,13 @@ class MidiFeedbackAPCKey25Plugin(MidiFeedbackPlugin):
colour = self.COLOUR_GREEN colour = self.COLOUR_GREEN
else: else:
colour = self.COLOUR_AMBER colour = self.COLOUR_AMBER
if plugin.selected_clip==i: #blink if selected if plugin.selected_clip == i: # blink if selected
colour += self.BLINK colour += self.BLINK
elif plugin.selected_clip==i: elif plugin.selected_clip == i:
colour = self.COLOUR_RED_BLINK colour = self.COLOUR_RED_BLINK
else: else:
colour = self.COLOUR_OFF colour = self.COLOUR_OFF
self.set_status(command='note_on', note=self.NOTE_CLIP_STATUS_ROW+i, velocity=colour) self.set_status(command='note_on', note=self.NOTE_CLIP_STATUS_ROW + i, velocity=colour)
""" # doesnt really work well, but shows progress of clip in leds """ # doesnt really work well, but shows progress of clip in leds
if plugin.is_playing() and not plugin.is_paused(): if plugin.is_playing() and not plugin.is_paused():
@@ -149,28 +150,28 @@ class MidiFeedbackAPCKey25Plugin(MidiFeedbackPlugin):
""" """
except Exception as e: except Exception as e:
pass pass
#print ("Warning: Failed when running plugin feedback for ShaderLoopRecordPlugin:\t%s" % str(e)) # print ("Warning: Failed when running plugin feedback for ShaderLoopRecordPlugin:\t%s" % str(e))
try: try:
from plugins.ShaderQuickPresetPlugin import ShaderQuickPresetPlugin from plugins.ShaderQuickPresetPlugin import ShaderQuickPresetPlugin
#print ("feedback_plugin_status") # print ("feedback_plugin_status")
for plugin in self.pc.get_plugins(ShaderQuickPresetPlugin): for plugin in self.pc.get_plugins(ShaderQuickPresetPlugin):
#print ("for plugin %s" % plugin) # print ("for plugin %s" % plugin)
for pad in range(0,8): for pad in range(0, 8):
#print ("checking selected_preset %s vs pad %s" % (plugin.selected_preset, pad)) # print ("checking selected_preset %s vs pad %s" % (plugin.selected_preset, pad))
colour = self.COLOUR_OFF colour = self.COLOUR_OFF
if plugin.presets[pad] is not None: if plugin.presets[pad] is not None:
colour = self.COLOUR_AMBER colour = self.COLOUR_AMBER
if plugin.last_recalled==pad: if plugin.last_recalled == pad:
colour = self.COLOUR_GREEN colour = self.COLOUR_GREEN
if plugin.selected_preset==pad: if plugin.selected_preset == pad:
if plugin.presets[pad] is None: if plugin.presets[pad] is None:
colour = self.COLOUR_RED colour = self.COLOUR_RED
colour += self.BLINK colour += self.BLINK
self.set_status(command='note_on', note=self.NOTE_SHADER_PRESET_ROW+pad, velocity=colour) self.set_status(command='note_on', note=self.NOTE_SHADER_PRESET_ROW + pad, velocity=colour)
except Exception as e: except Exception as e:
pass pass
#print ("Warning: Failed when running plugin feedback for ShaderQuickPresetPlugin:\t%s" % str(e)) # print ("Warning: Failed when running plugin feedback for ShaderQuickPresetPlugin:\t%s" % str(e))
BLINK = 1 BLINK = 1
COLOUR_OFF = 0 COLOUR_OFF = 0
@@ -189,7 +190,7 @@ class MidiFeedbackAPCKey25Plugin(MidiFeedbackPlugin):
# show if internal feedback (the shader layer kind) is enabled # show if internal feedback (the shader layer kind) is enabled
if self.pc.data.feedback_active and not self.pc.data.function_on: if self.pc.data.feedback_active and not self.pc.data.function_on:
self.feedback_shader_feedback(self.COLOUR_GREEN) self.feedback_shader_feedback(self.COLOUR_GREEN)
#elif self.pc.data.settings['shader']['X3_AS_SPEED']['value'] == 'enabled' and self.pc.data.function_on: # elif self.pc.data.settings['shader']['X3_AS_SPEED']['value'] == 'enabled' and self.pc.data.function_on:
# self.feedback_shader_feedback(self.COLOUR_GREEN_BLINK) # self.feedback_shader_feedback(self.COLOUR_GREEN_BLINK)
else: else:
self.feedback_shader_feedback(self.COLOUR_OFF) self.feedback_shader_feedback(self.COLOUR_OFF)
@@ -204,16 +205,16 @@ class MidiFeedbackAPCKey25Plugin(MidiFeedbackPlugin):
self.feedback_plugin_status() self.feedback_plugin_status()
for n,shader in enumerate(self.pc.message_handler.shaders.selected_shader_list): for n, shader in enumerate(self.pc.message_handler.shaders.selected_shader_list):
#print ("%s: in refresh_midi_feedback, got shader: %s" % (n,shader)) # print ("%s: in refresh_midi_feedback, got shader: %s" % (n,shader))
# show if layer is running or not # show if layer is running or not
if not self.pc.data.function_on: if not self.pc.data.function_on:
if self.pc.message_handler.shaders.selected_status_list[n] == '': if self.pc.message_handler.shaders.selected_status_list[n] == '':
self.feedback_shader_layer_on(n) self.feedback_shader_layer_on(n)
else: else:
self.feedback_shader_layer_off(n) self.feedback_shader_layer_off(n)
for x in range(0,8): for x in range(0, 8):
if 'slot' in shader and shader.get('slot',None)==x: if 'slot' in shader and shader.get('slot', None) == x:
if self.pc.message_handler.shaders.selected_status_list[n] == '': if self.pc.message_handler.shaders.selected_status_list[n] == '':
# show that slot is selected and running # show that slot is selected and running
self.feedback_shader_on(n, x, self.COLOUR_GREEN) self.feedback_shader_on(n, x, self.COLOUR_GREEN)
@@ -229,15 +230,16 @@ class MidiFeedbackAPCKey25Plugin(MidiFeedbackPlugin):
self.update_device() self.update_device()
#print("refresh_midi_feedback") # print("refresh_midi_feedback")
last_state = None last_state = None
def update_device(self): def update_device(self):
from copy import deepcopy from copy import deepcopy
#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 (i not in self.last_state 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

@@ -1,8 +1,9 @@
import plugins import plugins
#from plugins.MidiFeedbackAPCKey25Plugin import MidiFeedbackAPCKey25Plugin
# from plugins.MidiFeedbackAPCKey25Plugin import MidiFeedbackAPCKey25Plugin
class MidiFeedbackLaunchpadPlugin(plugins.MidiFeedbackAPCKey25Plugin.MidiFeedbackAPCKey25Plugin): class MidiFeedbackLaunchpadPlugin(plugins.MidiFeedbackAPCKey25Plugin.MidiFeedbackAPCKey25Plugin):
status = {} status = {}
def __init__(self, plugin_collection): def __init__(self, plugin_collection):
@@ -10,15 +11,15 @@ class MidiFeedbackLaunchpadPlugin(plugins.MidiFeedbackAPCKey25Plugin.MidiFeedbac
self.description = 'Outputs feedback to Novation Launchpad' self.description = 'Outputs feedback to Novation Launchpad'
def init_notes(self): def init_notes(self):
self.NOTE_PLAY_SHADER = self.get_note('play_shader_0_0',0) self.NOTE_PLAY_SHADER = self.get_note('play_shader_0_0', 0)
self.NOTE_SHADER_FEEDBACK = self.get_note('toggle_feedback',85) self.NOTE_SHADER_FEEDBACK = self.get_note('toggle_feedback', 85)
self.NOTE_SCENE_LAUNCH_COLUMN = self.get_note('toggle_shader_layer_0',82) self.NOTE_SCENE_LAUNCH_COLUMN = self.get_note('toggle_shader_layer_0', 82)
self.NOTE_MODULATION_COLUMN = self.get_note('select_shader_modulation_slot_0', self.NOTE_SCENE_LAUNCH_COLUMN) self.NOTE_MODULATION_COLUMN = self.get_note('select_shader_modulation_slot_0', self.NOTE_SCENE_LAUNCH_COLUMN)
self.NOTE_CAPTURE_PREVIEW = self.get_note('toggle_capture_preview', 86) self.NOTE_CAPTURE_PREVIEW = self.get_note('toggle_capture_preview', 86)
self.NOTE_CLIP_STATUS_ROW = self.get_note('toggle_automation_clip_0', 8) self.NOTE_CLIP_STATUS_ROW = self.get_note('toggle_automation_clip_0', 8)
self.NOTE_SHADER_PRESET_ROW = self.get_note('select_preset_0', 112) self.NOTE_SHADER_PRESET_ROW = self.get_note('select_preset_0', 112)
self.NOTE_SHADER_LAYER_ON = [ self.NOTE_SHADER_LAYER_ON = [
self.get_note('toggle_shader_layer_%i'%i,8+(i*16)) for i in range(0,3) self.get_note('toggle_shader_layer_%i' % i, 8 + (i * 16)) for i in range(0, 3)
] ]
def supports_midi_feedback(self, device_name): def supports_midi_feedback(self, device_name):
@@ -28,16 +29,17 @@ class MidiFeedbackLaunchpadPlugin(plugins.MidiFeedbackAPCKey25Plugin.MidiFeedbac
return True return True
def feedback_shader_on(self, layer, slot, colour=None): def feedback_shader_on(self, layer, slot, colour=None):
if colour is None: colour = self.COLOUR_GREEN if colour is None:
self.set_status(note=(self.NOTE_PLAY_SHADER+(layer)*16)+slot, velocity=int(colour)) 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): def feedback_shader_off(self, layer, slot):
self.set_status(note=(self.NOTE_PLAY_SHADER+(layer)*16)+slot, velocity=self.COLOUR_OFF) self.set_status(note=(self.NOTE_PLAY_SHADER + (layer) * 16) + slot, velocity=self.COLOUR_OFF)
# TODO: make these colours correct+sensible # TODO: make these colours correct+sensible
BLINK = 1 BLINK = 1
COLOUR_OFF = 0 COLOUR_OFF = 0
COLOUR_GREEN = 8 #1 COLOUR_GREEN = 8 # 1
COLOUR_GREEN_BLINK = 15 COLOUR_GREEN_BLINK = 15
COLOUR_RED = 32 COLOUR_RED = 32
COLOUR_RED_BLINK = 47 COLOUR_RED_BLINK = 47

View File

@@ -1,5 +1,6 @@
from data_centre.plugin_collection import ActionsPlugin from data_centre.plugin_collection import ActionsPlugin
class MultiActionsPlugin(ActionsPlugin): class MultiActionsPlugin(ActionsPlugin):
disabled = False # this is only a demo of very basic multi-actions plugin -- superceded by ManipulatePlugin disabled = False # this is only a demo of very basic multi-actions plugin -- superceded by ManipulatePlugin
@@ -15,7 +16,7 @@ class MultiActionsPlugin(ActionsPlugin):
@property @property
def parserlist(self): def parserlist(self):
return [ return [
( r"(.*)&&(.*)", self.run_multi ), (r"(.*)&&(.*)", self.run_multi),
] ]
def run_multi(self, action1, action2, value): def run_multi(self, action1, action2, value):

View File

@@ -1,9 +1,8 @@
from data_centre.plugin_collection import ActionsPlugin, SequencePlugin, DisplayPlugin from data_centre.plugin_collection import ActionsPlugin, DisplayPlugin, SequencePlugin
from plugins.frame_manager import Frame from plugins.frame_manager import Frame
class ShaderLoopRecordPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin): class ShaderLoopRecordPlugin(ActionsPlugin, SequencePlugin, DisplayPlugin):
MAX_CLIPS = 8 MAX_CLIPS = 8
frames = [] frames = []
@@ -21,25 +20,25 @@ class ShaderLoopRecordPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin):
self.reset_ignored() self.reset_ignored()
def load_presets(self): def load_presets(self):
#try: # try:
print("trying load presets? %s " % self.PRESET_FILE_NAME) print("trying load presets? %s " % self.PRESET_FILE_NAME)
p = self.pc.read_json(self.PRESET_FILE_NAME) p = self.pc.read_json(self.PRESET_FILE_NAME)
if p: if p:
while len(p)<self.MAX_CLIPS: while len(p) < self.MAX_CLIPS:
print ("adding clip ") print("adding clip ")
p += self.get_empty_clip(self.duration) #[ [None] ] #*((int(self.duration / self.frequency))-len(p)) ] p += self.get_empty_clip(self.duration) # [ [None] ] #*((int(self.duration / self.frequency))-len(p)) ]
for i in p: for i in p:
print("got automation clip of duration %s" % len(i)) print("got automation clip of duration %s" % len(i))
if i and len(i)<(int(self.duration / self.frequency)): if i and len(i) < (int(self.duration / self.frequency)):
print("adding more slots due to size change") print("adding more slots due to size change")
i += [None]*((int(self.duration / self.frequency))-len(i)) i += [None] * ((int(self.duration / self.frequency)) - len(i))
print("len is now %s" % len(i)) print("len is now %s" % len(i))
return p return p
elif p: elif p:
return p return p
else: else:
return self.get_factory_reset() return self.get_factory_reset()
#except: # except:
# return self.clear_frames() # return self.clear_frames()
def save_presets(self): def save_presets(self):
@@ -51,41 +50,41 @@ class ShaderLoopRecordPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin):
# DisplayPlugin methods # DisplayPlugin methods
def get_display_modes(self): def get_display_modes(self):
return ['LOOPREC','NAV_LPRC'] return ['LOOPREC', 'NAV_LPRC']
def show_plugin(self, display, display_mode): def show_plugin(self, display, display_mode):
from tkinter import END from tkinter import END
#super(DisplayPlugin).show_plugin(display, display_mode) # super(DisplayPlugin).show_plugin(display, display_mode)
display.display_text.insert(END, '{} \n'.format(display.body_title)) display.display_text.insert(END, '{} \n'.format(display.body_title))
display.display_text.insert(END, "test from ShaderLoopRecordPlugin!\n") display.display_text.insert(END, "test from ShaderLoopRecordPlugin!\n")
status = "" status = ""
status+="playing" if self.is_playing() else "stopped" status += "playing" if self.is_playing() else "stopped"
status+="\t" status += "\t"
status+="paused" if self.is_paused() else "unpaused" status += "paused" if self.is_paused() else "unpaused"
status+="\t" status += "\t"
status+="REC" if self.recording else "---" status += "REC" if self.recording else "---"
status+="*" if self.is_ignoring() else " " status += "*" if self.is_ignoring() else " "
status+="\t" status += "\t"
status+="Overdub" if self.overdub else "-------" status += "Overdub" if self.overdub else "-------"
status+="\t" status += "\t"
status+="Looping" if self.looping else "Once" status += "Looping" if self.looping else "Once"
status+="\n" status += "\n"
display.display_text.insert(END, status) display.display_text.insert(END, status)
display.display_text.insert(END, ("Position:\t{:3.0f}%\t[{:12s}]".format(self.position*100.0,("#"*int(self.position*12))))) display.display_text.insert(END, ("Position:\t{:3.0f}%\t[{:12s}]".format(self.position * 100.0, ("#" * int(self.position * 12)))))
#display.display_text.insert(END, (" Speed: {:03.2f}%\n".format(self.speed*100))) # display.display_text.insert(END, (" Speed: {:03.2f}%\n".format(self.speed*100)))
display.display_text.insert(END, (" Speed:{} {:3.0f}%\n".format(display.get_speed_indicator(self.speed/2,convert=False),self.speed*100))) display.display_text.insert(END, (" Speed:{} {:3.0f}%\n".format(display.get_speed_indicator(self.speed / 2, convert=False), self.speed * 100)))
if self.speed==0.0: if self.speed == 0.0:
display.display_text.insert(END, ("Duration:\tinfinity!\n")) display.display_text.insert(END, ("Duration:\tinfinity!\n"))
else: else:
display.display_text.insert(END, ("Duration:\t{:03.2f}s\n".format(((self.duration/1000)/self.speed)/4))) display.display_text.insert(END, ("Duration:\t{:03.2f}s\n".format(((self.duration / 1000) / self.speed) / 4)))
#distance s = d/t d = s*t t = d/s # distance s = d/t d = s*t t = d/s
status = "\nEnabled clips:\t" status = "\nEnabled clips:\t"
for i in range(0,self.MAX_CLIPS): for i in range(0, self.MAX_CLIPS):
status+="#" if i==self.selected_clip and i in self.running_clips else\ status += "#" if i == self.selected_clip and i in self.running_clips else \
"/" if i==self.selected_clip and i not in self.running_clips else\ "/" if i == self.selected_clip and i not in self.running_clips else \
"=" if i in self.running_clips else\ "=" if i in self.running_clips else \
'_' '_'
status += "\n" status += "\n"
display.display_text.insert(END, status) display.display_text.insert(END, status)
@@ -93,30 +92,27 @@ class ShaderLoopRecordPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin):
"""for key,value in self.variables.items(): """for key,value in self.variables.items():
display.display_text.insert(END, "\t" + key + "\t{:03.2f}\n".format(value))""" display.display_text.insert(END, "\t" + key + "\t{:03.2f}\n".format(value))"""
@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),
( r"toggle_record_automation", self.toggle_record_automation ), (r"toggle_record_automation", self.toggle_record_automation),
( r"toggle_overdub_automation", self.toggle_overdub_automation ), (r"toggle_overdub_automation", self.toggle_overdub_automation),
( r"clear_automation", self.clear_clip ), (r"clear_automation", self.clear_clip),
( r"select_automation_clip_([0-7])", self.select_clip ), (r"select_automation_clip_([0-7])", self.select_clip),
( r"toggle_automation_clip_([0-7])", self.toggle_clip ), (r"toggle_automation_clip_([0-7])", self.toggle_clip),
#( r"smooth_clip_(0-7])", self.smooth_clip ), # ( r"smooth_clip_(0-7])", self.smooth_clip ),
( r"smooth_selected_clip", self.smooth_selected_clip ) (r"smooth_selected_clip", self.smooth_selected_clip)
] ]
def smooth_selected_clip(self): def smooth_selected_clip(self):
self.pc.fm.interpolate_clip(self.frames[self.selected_clip]) self.pc.fm.interpolate_clip(self.frames[self.selected_clip])
def toggle_overdub_automation(self): def toggle_overdub_automation(self):
self.overdub = not self.overdub self.overdub = not self.overdub
if not self.overdub: if not self.overdub:
@@ -132,36 +128,37 @@ class ShaderLoopRecordPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin):
self.last_saved_index = None self.last_saved_index = None
self.save_presets() self.save_presets()
def get_empty_clip(self, duration = 4000): def get_empty_clip(self, duration=4000):
return [None] * (int(duration / self.frequency)) return [None] * (int(duration / self.frequency))
def get_factory_reset(self): def get_factory_reset(self):
return [ self.get_empty_clip(self.duration) for i in range(self.MAX_CLIPS) ] return [self.get_empty_clip(self.duration) for i in range(self.MAX_CLIPS)]
def clear_clip(self,clip = None): def clear_clip(self, clip=None):
if clip is None: if clip is None:
clip = self.selected_clip clip = self.selected_clip
self.frames[clip] = self.get_empty_clip(self.duration) * self.MAX_CLIPS self.frames[clip] = self.get_empty_clip(self.duration) * self.MAX_CLIPS
self.reset_ignored() 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 return self.frames
def toggle_clip(self,clip = None): def toggle_clip(self, clip=None):
if clip is None: if clip is None:
clip = self.selected_clip clip = self.selected_clip
else: else:
self.selected_clip = clip self.selected_clip = clip
#self.running_clips[clip] = not self.running_clips[clip] # self.running_clips[clip] = not self.running_clips[clip]
if clip in self.running_clips: if clip in self.running_clips:
self.running_clips.remove(clip) self.running_clips.remove(clip)
else: else:
self.running_clips.append(clip) self.running_clips.append(clip)
print("running clips looks like %s" %self.running_clips) print("running clips looks like %s" % self.running_clips)
def reset_ignored(self): def reset_ignored(self):
# print("!!!!resetting ignored") # print("!!!!resetting ignored")
self.ignored = Frame(self.pc).store_copy({ 'shader_params': [[None]*4,[None]*4,[None]*4] }) self.ignored = Frame(self.pc).store_copy({'shader_params': [[None] * 4, [None] * 4, [None] * 4]})
def is_ignoring(self): def is_ignoring(self):
return not self.pc.fm.is_frame_empty(self.ignored) return not self.pc.fm.is_frame_empty(self.ignored)
@@ -170,58 +167,67 @@ class ShaderLoopRecordPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin):
self.selected_clip = clip self.selected_clip = clip
selected_clip = 0 selected_clip = 0
running_clips = [ ] #False ] * self.MAX_CLIPS running_clips = [] # False ] * self.MAX_CLIPS
duration = 4000 duration = 4000
frequency = 10 #25 frequency = 10 # 25
recording = False recording = False
overdub = True overdub = True
#ignored = None # set in reset_ignored in init - used for tracking what parans have changed since overdub # ignored = None # set in reset_ignored in init - used for tracking what parans have changed since overdub
last_frame = None # for tracking what's changed between frames when overdubbing last_frame = None # for tracking what's changed between frames when overdubbing
last_saved_index = None # for backfilling last_saved_index = None # for backfilling
DEBUG_FRAMES = False#True DEBUG_FRAMES = False # True
def run_sequence(self, position): def run_sequence(self, position):
current_frame_index = int(position * (int(self.duration / self.frequency))) current_frame_index = int(position * (int(self.duration / self.frequency)))
if current_frame_index<0: if current_frame_index < 0:
current_frame_index = (self.duration/self.frequency) - current_frame_index current_frame_index = (self.duration / self.frequency) - current_frame_index
if current_frame_index >= self.duration: # self.duration/self.frequency: if current_frame_index >= self.duration: # self.duration/self.frequency:
current_frame_index = "(self.duration/self.frequency) +""" (current_frame_index%self.duration) 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("got frame index %s" % current_frame_index) print(">>>>>>>>>>>>>>frame at %i%%: %i" % (position * 100, current_frame_index))
# print("got frame index %s" % current_frame_index)
if self.recording: if self.recording:
current_frame = self.pc.fm.get_live_frame() #.copy() current_frame = self.pc.fm.get_live_frame() # .copy()
selected_clip = self.selected_clip 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 ("%s clips, looks like %s" % (len(self.frames),self.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) # print("selected_clip is %s "%selected_clip)
#clip = self.frames[selected_clip] # clip = self.frames[selected_clip]
if self.is_playing() and self.recording and self.selected_clip not in self.running_clips: if self.is_playing() and self.recording and self.selected_clip not in self.running_clips:
self.running_clips += [ self.selected_clip ] self.running_clips += [self.selected_clip]
if self.recording: if self.recording:
current_frame = self.pc.fm.get_live_frame() #.copy() 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: for selected_clip in self.running_clips:
saved_frame = self.frames[selected_clip][current_frame_index] saved_frame = self.frames[selected_clip][current_frame_index]
if not self.recording or (selected_clip!=self.selected_clip): if not self.recording or (selected_clip != self.selected_clip):
self.pc.fm.recall_frame(saved_frame) self.pc.fm.recall_frame(saved_frame)
if self.recording and selected_clip==self.selected_clip: if self.recording and selected_clip == self.selected_clip:
if self.last_frame is None: if self.last_frame is None:
self.last_frame = current_frame 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:
if self.DEBUG_FRAMES: print("current f is \t\t%s" % current_frame['shader_params']) print("last frame is \t\t%s" % self.last_frame['shader_params'])
diff = self.pc.fm.get_frame_diff(self.last_frame,current_frame) if self.DEBUG_FRAMES:
if self.DEBUG_FRAMES: print("diffed frame is \t%s" % diff['shader_params']) 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.overdub and saved_frame: if self.overdub and saved_frame:
# add the params tweaked this frame to the params to be ignored by recall # 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) 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("got self.ignored:\n\t%s\n" % self.ignored.f)
print("diff is currently:\n\t%s\n" % diff.f) print("diff is currently:\n\t%s\n" % diff.f)
print("saved_frame is currently:\n\t%s\n" % saved_frame.f)""" print("saved_frame is currently:\n\t%s\n" % saved_frame.f)"""
@@ -229,22 +235,24 @@ class ShaderLoopRecordPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin):
self.pc.fm.get_frame_ignored(saved_frame, self.ignored), self.pc.fm.get_frame_ignored(saved_frame, self.ignored),
diff diff
) )
#print("got merged:\n\t%s\n" % diff.f) # print("got merged:\n\t%s\n" % diff.f)
#diff = self.pc.shaders.merge_frames(self.pc.shaders.get_live_frame(), diff) # diff = self.pc.shaders.merge_frames(self.pc.shaders.get_live_frame(), diff)
self.pc.fm.recall_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:
if self.DEBUG_FRAMES: print("||||saving frame \t%s" % (diff['shader_params'])) print("after diff2 is: \t%s" % diff['shader_params'])
self.frames[selected_clip][current_frame_index] = diff #self.get_frame_diff(self.last_frame,current_frame) if self.DEBUG_FRAMES:
#backfill 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: """if self.last_saved_index is not None:
if self.DEBUG_FRAMES: print ("last_saved_index is %s, current_frame_index is %s" % (self.last_saved_index, current_frame_index)) if self.DEBUG_FRAMES: print ("last_saved_index is %s, current_frame_index is %s" % (self.last_saved_index, current_frame_index))
for i in range(current_frame_index - (self.last_saved_index) ): for i in range(current_frame_index - (self.last_saved_index) ):
if self.DEBUG_FRAMES: print("backfilling frame %s" % ((self.last_saved_index+i+1)%len(self.frames[selected_clip]))) if self.DEBUG_FRAMES: print("backfilling frame %s" % ((self.last_saved_index+i+1)%len(self.frames[selected_clip])))
self.frames[selected_clip][(self.last_saved_index+i+1)%len(self.frames[selected_clip])] = diff""" 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_saved_index = current_frame_index
self.last_frame = self.pc.fm.get_live_frame() #diff 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): """def recall_frame_index(self, index):
self.pc.shaders.recall_frame_params(self.frames[index].copy())""" self.pc.shaders.recall_frame_params(self.frames[index].copy())"""

View File

@@ -1,7 +1,8 @@
from data_centre.plugin_collection import ActionsPlugin, DisplayPlugin from data_centre.plugin_collection import ActionsPlugin, DisplayPlugin
from plugins.frame_manager import Frame from plugins.frame_manager import Frame
class ShaderQuickPresetPlugin(ActionsPlugin,DisplayPlugin): #,SequencePlugin):
class ShaderQuickPresetPlugin(ActionsPlugin, DisplayPlugin): # ,SequencePlugin):
MAX_PRESETS = 8 MAX_PRESETS = 8
display_live_on = False display_live_on = False
@@ -18,7 +19,7 @@ class ShaderQuickPresetPlugin(ActionsPlugin,DisplayPlugin): #,SequencePlugin):
def load_presets(self): def load_presets(self):
print("trying load presets? %s " % self.PRESET_FILE_NAME) print("trying load presets? %s " % self.PRESET_FILE_NAME)
return [ Frame(self.pc).store_copy(x) for x in (self.pc.read_json(self.PRESET_FILE_NAME) or ([None]*self.MAX_PRESETS)) ] return [Frame(self.pc).store_copy(x) for x in (self.pc.read_json(self.PRESET_FILE_NAME) or ([None] * self.MAX_PRESETS))]
def save_presets(self): def save_presets(self):
self.pc.update_json(self.PRESET_FILE_NAME, self.presets) self.pc.update_json(self.PRESET_FILE_NAME, self.presets)
@@ -30,19 +31,19 @@ class ShaderQuickPresetPlugin(ActionsPlugin,DisplayPlugin): #,SequencePlugin):
@property @property
def parserlist(self): def parserlist(self):
return [ return [
( r"load_presets", self.load_presets ), (r"load_presets", self.load_presets),
( r"save_presets", self.save_presets ), (r"save_presets", self.save_presets),
( r"store_next_preset", self.store_next_preset ), (r"store_next_preset", self.store_next_preset),
( r"store_current_preset", self.store_current_preset ), (r"store_current_preset", self.store_current_preset),
( r"switch_to_preset_([0-%i])"%self.MAX_PRESETS, self.switch_to_preset ), (r"switch_to_preset_([0-%i])" % self.MAX_PRESETS, self.switch_to_preset),
( r"select_preset_([0-%i])"%self.MAX_PRESETS, self.select_preset ), (r"select_preset_([0-%i])" % self.MAX_PRESETS, self.select_preset),
( r"clear_current_preset", self.clear_current_preset ), (r"clear_current_preset", self.clear_current_preset),
( r"qksh_toggle_display_live", self.toggle_display_live ), (r"qksh_toggle_display_live", self.toggle_display_live),
( r"switch_to_next_preset", self.switch_to_next_preset ), (r"switch_to_next_preset", self.switch_to_next_preset),
( r"switch_to_previous_preset", self.switch_to_previous_preset ), (r"switch_to_previous_preset", self.switch_to_previous_preset),
( r"switch_to_current_preset", self.switch_to_current_preset ), (r"switch_to_current_preset", self.switch_to_current_preset),
( r"select_previous_preset", self.select_previous_preset ), (r"select_previous_preset", self.select_previous_preset),
( r"select_next_preset", self.select_next_preset ), (r"select_next_preset", self.select_next_preset),
] ]
def toggle_display_live(self): def toggle_display_live(self):
@@ -50,16 +51,16 @@ class ShaderQuickPresetPlugin(ActionsPlugin,DisplayPlugin): #,SequencePlugin):
# DisplayPlugin methods # DisplayPlugin methods
def get_display_modes(self): def get_display_modes(self):
return ['QUIKSHDR',['NAV_QKSH','PLAY_SHADER']] return ['QUIKSHDR', ['NAV_QKSH', 'PLAY_SHADER']]
def show_plugin(self, display, display_mode): def show_plugin(self, display, display_mode):
from tkinter import END from tkinter import END
#super(DisplayPlugin).show_plugin(display, display_mode) # super(DisplayPlugin).show_plugin(display, display_mode)
display.display_text.insert(END, '{} \n'.format(display.body_title)) display.display_text.insert(END, '{} \n'.format(display.body_title))
display.display_text.insert(END, "ShaderQuickPresetPlugin") display.display_text.insert(END, "ShaderQuickPresetPlugin")
status = "Selected: [" status = "Selected: ["
#for i,preset in enumerate(self.presets): # for i,preset in enumerate(self.presets):
for i in range(self.MAX_PRESETS): for i in range(self.MAX_PRESETS):
preset = self.presets[i] preset = self.presets[i]
if i == self.selected_preset: if i == self.selected_preset:
@@ -81,14 +82,14 @@ class ShaderQuickPresetPlugin(ActionsPlugin,DisplayPlugin): #,SequencePlugin):
display.display_text.insert(END, "Showing LIVE preview\n") display.display_text.insert(END, "Showing LIVE preview\n")
else: else:
display.display_text.insert(END, "Showing stored preset slot %s" % self.selected_preset) display.display_text.insert(END, "Showing stored preset slot %s" % self.selected_preset)
if self.selected_preset==self.last_recalled: if self.selected_preset == self.last_recalled:
display.display_text.insert(END, " [last switched]") display.display_text.insert(END, " [last switched]")
display.display_text.insert(END, "\n") display.display_text.insert(END, "\n")
## show a summary of the selected preset ## show a summary of the selected preset
if self.selected_preset is not None: if self.selected_preset is not None:
# TODO: switch to display current settings # TODO: switch to display current settings
#for line in self.pc.fm.get_live_frame().get_frame_summary(): # for line in self.pc.fm.get_live_frame().get_frame_summary():
for line in (self.presets[self.selected_preset] if not self.display_live_on else self.pc.fm.get_live_frame()).get_frame_summary(): for line in (self.presets[self.selected_preset] if not self.display_live_on else self.pc.fm.get_live_frame()).get_frame_summary():
display.display_text.insert(END, "%s\n" % line) display.display_text.insert(END, "%s\n" % line)
@@ -113,11 +114,12 @@ class ShaderQuickPresetPlugin(ActionsPlugin,DisplayPlugin): #,SequencePlugin):
self.save_presets() self.save_presets()
def store_current_preset(self): 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 insert_position = self.selected_preset
self.presets[insert_position] = self.pc.fm.get_live_frame() self.presets[insert_position] = self.pc.fm.get_live_frame()
#print ("stored %s at position %s" % (self.presets[insert_position], insert_position)) # print ("stored %s at position %s" % (self.presets[insert_position], insert_position))
self.selected_preset = insert_position self.selected_preset = insert_position
self.last_recalled = insert_position self.last_recalled = insert_position
@@ -127,18 +129,18 @@ class ShaderQuickPresetPlugin(ActionsPlugin,DisplayPlugin): #,SequencePlugin):
self.selected_preset = preset self.selected_preset = preset
def switch_to_preset(self, preset): def switch_to_preset(self, preset):
#if preset>len(self.presets): # if preset>len(self.presets):
if self.presets[preset] is None: if self.presets[preset] is None:
self.message_handler.set_message('ERROR',"No quick shader preset in slot %s!" % preset) self.message_handler.set_message('ERROR', "No quick shader preset in slot %s!" % preset)
self.selected_preset = preset self.selected_preset = preset
return return
print ("switching to preset %s" % preset) print("switching to preset %s" % preset)
self.selected_preset = preset self.selected_preset = preset
self.last_recalled = preset self.last_recalled = preset
preset = self.presets[preset] preset = self.presets[preset]
print ("recalled preset %s" % preset) print("recalled preset %s" % preset)
self.pc.fm.recall_frame(preset) self.pc.fm.recall_frame(preset)
def switch_to_current_preset(self): def switch_to_current_preset(self):
@@ -158,7 +160,7 @@ class ShaderQuickPresetPlugin(ActionsPlugin,DisplayPlugin): #,SequencePlugin):
self.selected_preset = 0 self.selected_preset = 0
return return
self.selected_preset += 1 self.selected_preset += 1
if self.selected_preset>=self.MAX_PRESETS: if self.selected_preset >= self.MAX_PRESETS:
self.selected_preset = 0 self.selected_preset = 0
def select_previous_preset(self): def select_previous_preset(self):
@@ -166,8 +168,5 @@ class ShaderQuickPresetPlugin(ActionsPlugin,DisplayPlugin): #,SequencePlugin):
self.selected_preset = self.MAX_PRESETS self.selected_preset = self.MAX_PRESETS
return return
self.selected_preset -= 1 self.selected_preset -= 1
if self.selected_preset<0: if self.selected_preset < 0:
self.selected_preset = self.MAX_PRESETS-1 self.selected_preset = self.MAX_PRESETS - 1

View File

@@ -5,12 +5,12 @@ import pyaudio
from data_centre.plugin_collection import ActionsPlugin, DisplayPlugin, SequencePlugin from data_centre.plugin_collection import ActionsPlugin, DisplayPlugin, SequencePlugin
#import matplotlib.pyplot as plt # import matplotlib.pyplot as plt
np.set_printoptions(suppress=True) # don't use scientific notationn np.set_printoptions(suppress=True) # don't use scientific notationn
class SoundReactPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin):
class SoundReactPlugin(ActionsPlugin, SequencePlugin, DisplayPlugin):
DEBUG = False DEBUG = False
active = True active = True
@@ -20,14 +20,14 @@ class SoundReactPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin):
stream = None stream = None
CHUNK = 4096 # number of data points to read at a time CHUNK = 4096 # number of data points to read at a time
RATE = 48000 #44100 # time resolution of the recording device (Hz) RATE = 48000 # 44100 # time resolution of the recording device (Hz)
frequency = 10 # how often messages are sampled+calculated+sent, not anything to do with audio frequency frequency = 10 # how often messages are sampled+calculated+sent, not anything to do with audio frequency
values = {} values = {}
levels = { levels = {
"energy": [ 0.0, 0.0, 1.0, 0.0 ], "energy": [0.0, 0.0, 1.0, 0.0],
"peakfreq": [ 0.0, 0.0, 0.0, 0.0 ] "peakfreq": [0.0, 0.0, 0.0, 0.0]
} }
last_values = {} last_values = {}
display_values = {} display_values = {}
@@ -44,9 +44,9 @@ class SoundReactPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin):
self.PRESET_FILE_NAME = "SoundReactPlugin/config.json" self.PRESET_FILE_NAME = "SoundReactPlugin/config.json"
presets = self.load_presets() presets = self.load_presets()
self.config = presets.get('config',self.config) self.config = presets.get('config', self.config)
self.levels = presets.get('levels',self.levels) self.levels = presets.get('levels', self.levels)
self.active = presets.get('active',self.active) self.active = presets.get('active', self.active)
if not self.disabled: if not self.disabled:
self.start_plugin() self.start_plugin()
@@ -56,7 +56,7 @@ class SoundReactPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin):
return self.pc.read_json(self.PRESET_FILE_NAME) or {} return self.pc.read_json(self.PRESET_FILE_NAME) or {}
def save_presets(self): def save_presets(self):
self.pc.update_json(self.PRESET_FILE_NAME, { 'config': self.config, 'levels': self.levels, 'active': self.active } ) self.pc.update_json(self.PRESET_FILE_NAME, {'config': self.config, 'levels': self.levels, 'active': self.active})
def stop_plugin(self): def stop_plugin(self):
super().stop_plugin() super().stop_plugin()
@@ -73,8 +73,8 @@ class SoundReactPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin):
def open_sound_device(self): def open_sound_device(self):
try: try:
self.p=pyaudio.PyAudio() self.p = pyaudio.PyAudio()
self.stream=self.p.open(format=pyaudio.paInt16,channels=1,rate=self.RATE,input=True, self.stream = self.p.open(format=pyaudio.paInt16, channels=1, rate=self.RATE, input=True,
frames_per_buffer=self.CHUNK) frames_per_buffer=self.CHUNK)
except: except:
print("Failed to open sound device - disabling SoundReactPlugin!") print("Failed to open sound device - disabling SoundReactPlugin!")
@@ -96,10 +96,10 @@ class SoundReactPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin):
# TODO: write more interpreters # TODO: write more interpreters
return { return {
"energy": self.energy, "energy": self.energy,
#"low": self.low, # "low": self.low,
#"mid": self.mid, # "mid": self.mid,
#"high": self.high, # "high": self.high,
#"peakfreq": self.peakfreq # "peakfreq": self.peakfreq
} }
# triggers? # triggers?
@@ -107,39 +107,40 @@ class SoundReactPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin):
# DisplayPlugin methods # DisplayPlugin methods
def get_display_modes(self): def get_display_modes(self):
return ['SOUNDMOD','NAV_SND'] return ['SOUNDMOD', 'NAV_SND']
def show_plugin(self, display, display_mode): def show_plugin(self, display, display_mode):
from tkinter import END from tkinter import END
#super(DisplayPlugin).show_plugin(display, display_mode) # super(DisplayPlugin).show_plugin(display, display_mode)
display.display_text.insert(END, '{} \n'.format(display.body_title)) display.display_text.insert(END, '{} \n'.format(display.body_title))
display.display_text.insert(END, "SoundReactPlugin - ") display.display_text.insert(END, "SoundReactPlugin - ")
display.display_text.insert(END, "ACTIVE\n" if self.active else "not active\n") display.display_text.insert(END, "ACTIVE\n" if self.active else "not active\n")
#display.display_text.insert(END, "\tSpeed: {:03.2f}\n\n".format(self.speed)) # display.display_text.insert(END, "\tSpeed: {:03.2f}\n\n".format(self.speed))
for sourcename in sorted(self.sources): for sourcename in sorted(self.sources):
value = "{:8}:\t".format(sourcename) value = "{:8}:\t".format(sourcename)
for i,level in enumerate(self.levels[sourcename]): for i, level in enumerate(self.levels[sourcename]):
g = self.pc.display.get_mod_slot_label(i)+'%s '%self.pc.display.get_bar(level) g = self.pc.display.get_mod_slot_label(i) + '%s ' % self.pc.display.get_bar(level)
value += g value += g
value += "\t" value += "\t"
value += self.display_values.get(sourcename) or "{:4.2f}%".format(self.values.get(sourcename,0)*100) or "None" value += self.display_values.get(sourcename) or "{:4.2f}%".format(self.values.get(sourcename, 0) * 100) or "None"
display.display_text.insert(END,value + "\n") display.display_text.insert(END, value + "\n")
"""display.display_text.insert(END, "%s\n" %self.last_lfo_status[lfo]) """display.display_text.insert(END, "%s\n" %self.last_lfo_status[lfo])
display.display_text.insert(END, "\t%s\n" % self.formula[lfo])""" display.display_text.insert(END, "\t%s\n" % self.formula[lfo])"""
#display.display_text.insert(END, "\nLevels:%s\n\n" % self.levels) # display.display_text.insert(END, "\nLevels:%s\n\n" % self.levels)
display.display_text.insert(END, "\n\n\n") display.display_text.insert(END, "\n\n\n")
energy_history = [] energy_history = []
def run_sequence(self, position): def run_sequence(self, position):
# position is irrelvant for this plugin, we just want to run continuously # position is irrelvant for this plugin, we just want to run continuously
if not self.active or self.stream is None: if not self.active or self.stream is None:
return return
data = np.fromstring(self.stream.read(self.CHUNK, exception_on_overflow = False),dtype=np.int16) data = np.fromstring(self.stream.read(self.CHUNK, exception_on_overflow=False), dtype=np.int16)
previous_value = {} previous_value = {}
for sourcename in self.sources: for sourcename in self.sources:
@@ -147,87 +148,87 @@ class SoundReactPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin):
self.values[sourcename] = value self.values[sourcename] = value
if value is None: if value is None:
continue continue
for slot,level in enumerate(self.levels.get(sourcename,[])): for slot, level in enumerate(self.levels.get(sourcename, [])):
if level>0.0 and self.values.get(sourcename)!=self.last_values.get(sourcename): if level > 0.0 and self.values.get(sourcename) != self.last_values.get(sourcename):
self.pc.actions.call_method_name("modulate_param_%s_to_amount_continuous"%slot, self.values[sourcename]) self.pc.actions.call_method_name("modulate_param_%s_to_amount_continuous" % slot, self.values[sourcename])
previous_value[sourcename] = self.last_values.get(sourcename) or value previous_value[sourcename] = self.last_values.get(sourcename) or value
self.last_values[sourcename] = self.values[sourcename] self.last_values[sourcename] = self.values[sourcename]
if sourcename is 'energy' and self.last_values.get('energy') is not None: if sourcename is 'energy' and self.last_values.get('energy') is not None:
diff = abs(self.last_values.get('energy',value)-previous_value.get(sourcename,value)) #mean(self.energy_history)) diff = abs(self.last_values.get('energy', value) - previous_value.get(sourcename, value)) # mean(self.energy_history))
if len(self.energy_history)>5: #self.duration: if len(self.energy_history) > 5: # self.duration:
meandiff = abs(diff-mean(self.energy_history[:int(len(self.energy_history)/2)])) meandiff = abs(diff - mean(self.energy_history[:int(len(self.energy_history) / 2)]))
#print (" diff is %s, meandiff %s" % (diff, meandiff)) # print (" diff is %s, meandiff %s" % (diff, meandiff))
if meandiff>=self.config['energy'].get('triggerthreshold',0.15): if meandiff >= self.config['energy'].get('triggerthreshold', 0.15):
self.energy_history = [] self.energy_history = []
print ("\n>>>>>>Triggering dynamic change for meandiff %s?\n" % meandiff) print("\n>>>>>>Triggering dynamic change for meandiff %s?\n" % meandiff)
# TODO: add configurable triggering - eg trigger next preset, next shader, next video.. # TODO: add configurable triggering - eg trigger next preset, next shader, next video..
#self.pc.actions.call_method_name("load_slot_%s_into_next_player"%randint(0,9)) # self.pc.actions.call_method_name("load_slot_%s_into_next_player"%randint(0,9))
self.energy_history.append(diff) #self.values.get(sourcename,0.0)) self.energy_history.append(diff) # self.values.get(sourcename,0.0))
#print("logging %s" % 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)
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 GAIN_MULT = 1.0
def energy(self,data):
peak=np.average(np.abs(data))*2 def energy(self, data):
value = (peak/2**16)/16 * 100 peak = np.average(np.abs(data)) * 2
value = (peak / 2 ** 16) / 16 * 100
value *= (self.GAIN_MULT * self.config['energy']['gain']) value *= (self.GAIN_MULT * self.config['energy']['gain'])
value = value - self.config['energy']['threshold'] value = value - self.config['energy']['threshold']
if value<0.0: if value < 0.0:
value = 0.0 value = 0.0
if value>1.0: if value > 1.0:
value = 1.0 value = 1.0
bars="#"*int(50*value) 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.display_values['energy'] = "{} gn:{} trsh:{} trg:{}".format(
self.pc.display.get_bar(value), self.pc.display.get_bar(value),
self.pc.display.get_bar(self.config['energy']['gain']), self.pc.display.get_bar(self.config['energy']['gain']),
self.pc.display.get_bar(self.config['energy']['threshold']), self.pc.display.get_bar(self.config['energy']['threshold']),
self.pc.display.get_bar(self.config['energy'].setdefault('triggerthreshold',0.15)) self.pc.display.get_bar(self.config['energy'].setdefault('triggerthreshold', 0.15))
) )
return value return value
# dont think this works properly, or maybe it do just be like that # dont think this works properly, or maybe it do just be like that
def peakfreq(self,data):
def peakfreq(self, data):
data = data.copy() * np.hanning(len(data)) # smooth the FFT by windowing data data = data.copy() * np.hanning(len(data)) # smooth the FFT by windowing data
fft = abs(np.fft.fft(data).real) fft = abs(np.fft.fft(data).real)
fft = fft[:int(len(fft)/2)] # keep only first half fft = fft[:int(len(fft) / 2)] # keep only first half
freq = np.fft.fftfreq(self.CHUNK,1.0/self.RATE) freq = np.fft.fftfreq(self.CHUNK, 1.0 / self.RATE)
freq = freq[:int(len(freq)/2)] # keep only first half freq = freq[:int(len(freq) / 2)] # keep only first half
freqPeak = freq[np.where(fft==np.max(fft))[0][0]]+1 freqPeak = freq[np.where(fft == np.max(fft))[0][0]] + 1
if freqPeak<400: if freqPeak < 400:
return False return False
value = freqPeak/2000 # ? value = freqPeak / 2000 # ?
#value = (value**16) # value = (value**16)
if self.DEBUG: print("peak frequency:\t%d\tHz\t(converted to %s)"%(freqPeak,value)) if self.DEBUG:
self.display_values['peakfreq'] = ("%d Hz\t"%freqPeak) + "{:03.2f}".format(value) 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 return value
# ActionsPlugin methods # ActionsPlugin methods
@property @property
def parserlist(self): def parserlist(self):
return [ return [
( r"^toggle_sound_react_active$", self.toggle_active ), (r"^toggle_sound_react_active$", self.toggle_active),
( r"^sound_set_config_([a-z]*)_([a-z]*)$", self.set_config ), (r"^sound_set_config_([a-z]*)_([a-z]*)$", self.set_config),
( r"^sound_set_modulation_([a-z]*)_slot_([0-3])_level$", self.set_modulation_source_slot_level ), (r"^sound_set_modulation_([a-z]*)_slot_([0-3])_level$", self.set_modulation_source_slot_level),
] ]
def set_modulation_source_slot_level(self, sourcename, slot, level): def set_modulation_source_slot_level(self, sourcename, slot, level):
self.levels.setdefault(sourcename,[0.0,0.0,0.0,0.0])[slot] = level self.levels.setdefault(sourcename, [0.0, 0.0, 0.0, 0.0])[slot] = level
def set_config(self, sourcename, setting, value): def set_config(self, sourcename, setting, value):
if type(self.config.get(sourcename,{}).get(setting)) is str: if type(self.config.get(sourcename, {}).get(setting)) is str:
print ("SoundReactPlugin: type of existing setting is string, probably doesnt make sense to set this to a value of this type!") print("SoundReactPlugin: type of existing setting is string, probably doesnt make sense to set this to a value of this type!")
self.config[sourcename][setting] = value self.config[sourcename][setting] = value
def toggle_active(self): def toggle_active(self):

View File

@@ -1,6 +1,7 @@
from data_centre.plugin_collection import ActionsPlugin, SequencePlugin from data_centre.plugin_collection import ActionsPlugin, SequencePlugin
class TestPlugin(ActionsPlugin,SequencePlugin):
class TestPlugin(ActionsPlugin, SequencePlugin):
disabled = True disabled = True
def __init__(self, plugin_collection): def __init__(self, plugin_collection):
@@ -9,28 +10,29 @@ class TestPlugin(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),
( r"^print_arguments$", self.print_arguments ), (r"^print_arguments$", self.print_arguments),
( r"^set_the_shader_param_([0-3])_layer_offset_([0-2])_continuous_inverted_example$", self.invert_shader_param_layer ) (r"^set_the_shader_param_([0-3])_layer_offset_([0-2])_continuous_inverted_example$", self.invert_shader_param_layer)
] ]
def test_plugin(self): def test_plugin(self):
print ("TEST PLUGIN test_plugin CALLED!!") print("TEST PLUGIN test_plugin CALLED!!")
# can now access various parts of recur via self.pc # can now access various parts of recur via self.pc
cycle_count = 0 cycle_count = 0
def cycle_shaders(self): def cycle_shaders(self):
print ("Cycle shaders!!!") print("Cycle shaders!!!")
if self.cycle_count>9: if self.cycle_count > 9:
self.cycle_count = 0 self.cycle_count = 0
for i,shader in enumerate(self.pc.message_handler.shaders.selected_shader_list): for i, shader in enumerate(self.pc.message_handler.shaders.selected_shader_list):
self.pc.actions.call_method_name( self.pc.actions.call_method_name(
"play_shader_%s_%s" % (i, self.cycle_count), None "play_shader_%s_%s" % (i, self.cycle_count), None
) )
@@ -41,6 +43,7 @@ class TestPlugin(ActionsPlugin,SequencePlugin):
duration = 5000 duration = 5000
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_3_layer_0_continuous", position "set_the_shader_param_3_layer_0_continuous", position
@@ -56,7 +59,7 @@ class TestPlugin(ActionsPlugin,SequencePlugin):
def invert_shader_param_layer(self, param, layer, value): def invert_shader_param_layer(self, param, layer, value):
# invert the value # invert the value
self.pc.actions.call_method_name( self.pc.actions.call_method_name(
"set_the_shader_param_%s_layer_offset_%s_continuous" % ( param, layer), 1.0 - value "set_the_shader_param_%s_layer_offset_%s_continuous" % (param, layer), 1.0 - value
# if you were calling an action with no argument, use eg: # if you were calling an action with no argument, use eg:
# "toggle_automation_pause", None # "toggle_automation_pause", None
) )

View File

@@ -9,6 +9,7 @@ from data_centre.plugin_collection import ActionsPlugin, AutomationSourcePlugin,
class AsyncWriter(threading.Thread): class AsyncWriter(threading.Thread):
queue = [] queue = []
quit_flag = False quit_flag = False
def __init__(self, plugin): def __init__(self, plugin):
super().__init__() super().__init__()
self.plugin = plugin self.plugin = plugin
@@ -17,38 +18,38 @@ class AsyncWriter(threading.Thread):
self.queue.append(data) self.queue.append(data)
def ready(self): def ready(self):
return len(self.queue)>0 return len(self.queue) > 0
def quit(self): def quit(self):
self.quit_flag = True self.quit_flag = True
def run(self): def run(self):
while not self.quit_flag: while not self.quit_flag:
#print("AsyncWriter looping..") # print("AsyncWriter looping..")
if not self.plugin.active or self.plugin.disabled: if not self.plugin.active or self.plugin.disabled:
#print("plugin active or disabled - exiting!") # print("plugin active or disabled - exiting!")
return return
if self.plugin.ser is None or not self.plugin.ser: if self.plugin.ser is None or not self.plugin.ser:
#print("no stream - skipping") # print("no stream - skipping")
time.sleep(0.5) time.sleep(0.5)
continue continue
if not self.ready(): if not self.ready():
#print("not ready - skipping") # print("not ready - skipping")
time.sleep(0.005) time.sleep(0.005)
continue continue
item = self.queue.pop(0) item = self.queue.pop(0)
if item is not None: if item is not None:
#print("sending %s" % item) # print("sending %s" % item)
self.plugin.ser.write(item) self.plugin.ser.write(item)
time.sleep(len(item)*0.005) time.sleep(len(item) * 0.005)
else: else:
time.sleep(0.01) time.sleep(0.01)
if len(self.queue)>4: if len(self.queue) > 4:
self.queue = self.queue[-4:4] self.queue = self.queue[-4:4]
class WJSendPlugin(ActionsPlugin, SequencePlugin, DisplayPlugin, ModulationReceiverPlugin, AutomationSourcePlugin): class WJSendPlugin(ActionsPlugin, SequencePlugin, DisplayPlugin, ModulationReceiverPlugin, AutomationSourcePlugin):
DEBUG = False #True DEBUG = False # True
ser = None ser = None
active = True active = True
@@ -83,11 +84,11 @@ class WJSendPlugin(ActionsPlugin, SequencePlugin, DisplayPlugin, ModulationRecei
self.presets = self.load_presets() self.presets = self.load_presets()
print("read presets:\n%s\n" % self.presets) print("read presets:\n%s\n" % self.presets)
# load the stored modulation levels into the current config # load the stored modulation levels into the current config
for cmd,levels in self.presets['modulation_levels'].items(): for cmd, levels in self.presets['modulation_levels'].items():
self.commands[cmd]['modulation'] = levels.copy() self.commands[cmd]['modulation'] = levels.copy()
# build a reverse map of friendly name -> command struct for later use # build a reverse map of friendly name -> command struct for later use
for cmd,struct in self.commands.items(): for cmd, struct in self.commands.items():
self.command_by_queue[struct['queue']] = struct self.command_by_queue[struct['queue']] = struct
self.pc.actions.tk.after(500, self.start_plugin) self.pc.actions.tk.after(500, self.start_plugin)
@@ -96,11 +97,11 @@ class WJSendPlugin(ActionsPlugin, SequencePlugin, DisplayPlugin, ModulationRecei
def load_presets(self): def load_presets(self):
print("trying load presets? %s " % self.PRESET_FILE_NAME) print("trying load presets? %s " % self.PRESET_FILE_NAME)
return self.pc.read_json(self.PRESET_FILE_NAME) or { 'modulation_levels': {} } return self.pc.read_json(self.PRESET_FILE_NAME) or {'modulation_levels': {}}
def save_presets(self): def save_presets(self):
for cmd,struct in self.commands.items(): for cmd, struct in self.commands.items():
self.presets.setdefault('modulation_levels',{})[cmd] = struct.get('modulation',[{},{},{},{}]) self.presets.setdefault('modulation_levels', {})[cmd] = struct.get('modulation', [{}, {}, {}, {}])
self.pc.update_json(self.PRESET_FILE_NAME, self.presets) self.pc.update_json(self.PRESET_FILE_NAME, self.presets)
def start_plugin(self): def start_plugin(self):
@@ -113,14 +114,14 @@ class WJSendPlugin(ActionsPlugin, SequencePlugin, DisplayPlugin, ModulationRecei
self.asyncwriter = None self.asyncwriter = None
self.save_presets() self.save_presets()
# methods/vars for AutomationSourcePlugin # methods/vars for AutomationSourcePlugin
# a lot of the nitty-gritty handled in parent class, these are for interfacing to the plugin # a lot of the nitty-gritty handled in parent class, these are for interfacing to the plugin
last_record = {} last_record = {}
def get_frame_data(self): def get_frame_data(self):
diff = self.last_record.copy() diff = self.last_record.copy()
#self.last_record = {} # self.last_record = {}
#print(">>> reporting frame data for rec\n\t%s" % diff) # print(">>> reporting frame data for rec\n\t%s" % diff)
return diff return diff
def recall_frame_data(self, data): def recall_frame_data(self, data):
@@ -129,7 +130,7 @@ class WJSendPlugin(ActionsPlugin, SequencePlugin, DisplayPlugin, ModulationRecei
# print(">>>>recall from data:\n\t%s\n" %data) # print(">>>>recall from data:\n\t%s\n" %data)
for queue, item in data.items(): for queue, item in data.items():
if item is not None: if item is not None:
self.send_buffered(queue, item[0], item[1], record = False) self.send_buffered(queue, item[0], item[1], record=False)
def get_frame_summary(self, data): def get_frame_summary(self, data):
line = "WJMX: " line = "WJMX: "
@@ -141,43 +142,47 @@ class WJSendPlugin(ActionsPlugin, SequencePlugin, DisplayPlugin, ModulationRecei
# methods for ModulationReceiverPlugin - receives changes to the in-built modulation levels (-1 to +1) # methods for ModulationReceiverPlugin - receives changes to the in-built modulation levels (-1 to +1)
# experimental & hardcoded ! # experimental & hardcoded !
# TODO: make this not hardcoded and configurable mapping modulation to parameters, preferably on-the-fly.. # 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] modulation_value = [0.0, 0.0, 0.0, 0.0]
def set_modulation_value(self, param, value): def set_modulation_value(self, param, value):
self.modulation_value[param] = value ## invert so that no signal always gives a value .. self.modulation_value[param] = value ## invert so that no signal always gives a value ..
#print("storing modulation slot %s as %s" % (param,value)) # print("storing modulation slot %s as %s" % (param,value))
# take modulation value and throw it to local parameter # 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:
#v = (0.5+value)/2 print("||||| WJSendPlugin received set_modulation_value for param %s with value %s!" % (param, value))
# v = (0.5+value)/2
"""mapped = [ """mapped = [
'mix', 'mix',
'colour_T', 'colour_T',
#'colour_T', #'colour_T',
'back_colour:x' 'back_colour:x'
]""" ]"""
#self.catch_all(*mapped[param].split(":")+[v]) # self.catch_all(*mapped[param].split(":")+[v])
#self.commands[ # self.commands[
# find which commands are mapped to this modulation, and trigger a send of them # find which commands are mapped to this modulation, and trigger a send of them
# so that they update with the new modulation value # so that they update with the new modulation value
to_send = {} to_send = {}
for queue,cmd in sorted(self.command_by_queue.items(),reverse=True): for queue, cmd in sorted(self.command_by_queue.items(), reverse=True):
cmd.setdefault('modulation',[{},{},{},{}]) cmd.setdefault('modulation', [{}, {}, {}, {}])
if self.DEBUG: print("\tparam %s, checking modulation %s" % (param, cmd.get('modulation'))) if self.DEBUG:
if len(cmd['modulation'][param])>0: print("\tparam %s, checking modulation %s" % (param, cmd.get('modulation')))
if self.DEBUG: print("\tParam %s has modulation! sending update of values? %s" % if len(cmd['modulation'][param]) > 0:
(param, [cmd['arguments'][y] for y in cmd['arg_names'] ])) if self.DEBUG:
#self.send_buffered(cmd['queue'], cmd['form'], [x for x in [ cmd['arguments'][y] for y in cmd['arg_names'] ] ], record=False) 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 to_send[cmd['queue']] = cmd
continue continue
for queue,cmd in sorted(to_send.items(),reverse=True): for queue, cmd in sorted(to_send.items(), reverse=True):
self.send_buffered(cmd['queue'], cmd['form'], [x for x in [ cmd['arguments'][y] for y in cmd['arg_names'] ] ], record=False) self.send_buffered(cmd['queue'], cmd['form'], [x for x in [cmd['arguments'][y] for y in cmd['arg_names']]], record=False)
#with self.queue_lock: # with self.queue_lock:
#self.send(cmd['queue'], cmd['form'], [x for x in [ cmd['arguments'][y] for y in cmd['arg_names'] ] ]) # self.send(cmd['queue'], cmd['form'], [x for x in [ cmd['arguments'][y] for y in cmd['arg_names'] ] ])
#methods for DisplayPlugin # methods for DisplayPlugin
def show_plugin(self, display, display_mode): def show_plugin(self, display, display_mode):
from tkinter import END from tkinter import END
display.display_text.insert(END, '{} \n'.format(display.body_title)) display.display_text.insert(END, '{} \n'.format(display.body_title))
@@ -186,7 +191,7 @@ class WJSendPlugin(ActionsPlugin, SequencePlugin, DisplayPlugin, ModulationRecei
for queue, last in sorted(self.last_modulated.items()): for queue, last in sorted(self.last_modulated.items()):
is_selected = queue == self.commands[self.selected_command_name].get('queue') is_selected = queue == self.commands[self.selected_command_name].get('queue')
indicator = " " if not is_selected else "<" indicator = " " if not is_selected else "<"
display.display_text.insert(END, "%s%s:\t%s\t%s" % (indicator,queue,self.last.get(queue)[1],self.last_modulated.get(queue)[1])) display.display_text.insert(END, "%s%s:\t%s\t%s" % (indicator, queue, self.last.get(queue)[1], self.last_modulated.get(queue)[1]))
if is_selected: if is_selected:
display.display_text.insert(END, ">") # add indicator of the selected queue for param jobbies display.display_text.insert(END, ">") # add indicator of the selected queue for param jobbies
display.display_text.insert(END, "\n") display.display_text.insert(END, "\n")
@@ -194,23 +199,22 @@ class WJSendPlugin(ActionsPlugin, SequencePlugin, DisplayPlugin, ModulationRecei
cmd = self.commands[self.selected_command_name] cmd = self.commands[self.selected_command_name]
output = "\n" + "%s %s : %s\n" % (self.commands[self.selected_command_name].get('queue'), self.selected_command_name, cmd['name']) output = "\n" + "%s %s : %s\n" % (self.commands[self.selected_command_name].get('queue'), self.selected_command_name, cmd['name'])
for arg_name in cmd['arg_names']: for arg_name in cmd['arg_names']:
is_selected = cmd['arg_names'].index(arg_name)==self.selected_argument_index is_selected = cmd['arg_names'].index(arg_name) == self.selected_argument_index
output += "\t " #Mod output += "\t " # Mod
indicator = " " if not is_selected else "[" indicator = " " if not is_selected else "["
output += "%s%s: "%(indicator,arg_name) output += "%s%s: " % (indicator, arg_name)
for slot,mods in enumerate(cmd.setdefault('modulation',[{},{},{},{}])): for slot, mods in enumerate(cmd.setdefault('modulation', [{}, {}, {}, {}])):
#if arg_name in mods: # if arg_name in mods:
v = mods.get(arg_name,0.0) v = mods.get(arg_name, 0.0)
g = '%s'%self.pc.display.get_bar(v) g = '%s' % self.pc.display.get_bar(v)
output += "{}:{}|".format(self.pc.display.get_mod_slot_label(slot),g) output += "{}:{}|".format(self.pc.display.get_mod_slot_label(slot), g)
if is_selected: if is_selected:
output+="]" output += "]"
output += "\n" output += "\n"
display.display_text.insert(END, output+"\n") display.display_text.insert(END, output + "\n")
def get_display_modes(self): def get_display_modes(self):
return ["WJMXSEND","NAV_WJMX"] return ["WJMXSEND", "NAV_WJMX"]
# methods for SerialPlugin (TODO: if this needs generalising out!) and serial command queueing # methods for SerialPlugin (TODO: if this needs generalising out!) and serial command queueing
def open_serial(self, port='/dev/ttyUSB0', baudrate=9600): def open_serial(self, port='/dev/ttyUSB0', baudrate=9600):
@@ -227,17 +231,18 @@ class WJSendPlugin(ActionsPlugin, SequencePlugin, DisplayPlugin, ModulationRecei
stopbits=serial.STOPBITS_ONE, stopbits=serial.STOPBITS_ONE,
xonxoff=False, xonxoff=False,
rtscts=True, # TODO : test without this one rtscts=True, # TODO : test without this one
timeout=None #timeout timeout=None # timeout
) )
except Exception as e: except Exception as e:
print ("WJSendPlugin>> open_serial failed: " + str(type(e))) print("WJSendPlugin>> open_serial failed: " + str(type(e)))
self.disabled = True self.disabled = True
import traceback import traceback
traceback.print_exc() traceback.print_exc()
import threading import threading
serial_lock = threading.Lock() serial_lock = threading.Lock()
def send_serial_string(self, string): def send_serial_string(self, string):
# TODO: thread this so can implement throttling and reduce bottleneck... # TODO: thread this so can implement throttling and reduce bottleneck...
if not self.active: if not self.active:
@@ -246,13 +251,13 @@ class WJSendPlugin(ActionsPlugin, SequencePlugin, DisplayPlugin, ModulationRecei
if self.DEBUG: if self.DEBUG:
print("WJSendPlugin>> sending string %s " % string) print("WJSendPlugin>> sending string %s " % string)
output = b'\2' + string.encode('ascii') + b'\3' output = b'\2' + string.encode('ascii') + b'\3'
#with self.serial_lock: # with self.serial_lock:
#self.ser.write(b'\2\2\2\2\3\3\3\3') # self.ser.write(b'\2\2\2\2\3\3\3\3')
if self.asyncwriter is None: if self.asyncwriter is None:
self.asyncwriter = AsyncWriter(self) self.asyncwriter = AsyncWriter(self)
self.asyncwriter.start() self.asyncwriter.start()
self.asyncwriter.write(output) self.asyncwriter.write(output)
#self.ser.write(output) #.encode()) # self.ser.write(output) #.encode())
# TODO: sleeping here seems to help serial response lag problem? # TODO: sleeping here seems to help serial response lag problem?
"""self.sleep = 0.2 #self.pc.get_variable('A') """self.sleep = 0.2 #self.pc.get_variable('A')
#print ("got sleep %s" % self.sleep) #print ("got sleep %s" % self.sleep)
@@ -260,17 +265,18 @@ class WJSendPlugin(ActionsPlugin, SequencePlugin, DisplayPlugin, ModulationRecei
#print("using sleep %s" % self.sleep) #print("using sleep %s" % self.sleep)
import time import time
time.sleep(self.sleep/10.0)""" time.sleep(self.sleep/10.0)"""
#yield from self.ser.drain() # yield from self.ser.drain()
if self.DEBUG: if self.DEBUG:
print("send_serial_string: sent string '%s'" % output) #.encode('ascii')) print("send_serial_string: sent string '%s'" % output) # .encode('ascii'))
#if 'S' in string: # if 'S' in string:
# self.get_device_status() # self.get_device_status()
except Exception as e: except Exception as e:
print("\t%s: send_serial_string failed for '%s'" % (e,string)) print("\t%s: send_serial_string failed for '%s'" % (e, string))
queue = {} queue = {}
import threading import threading
queue_lock = threading.Lock() queue_lock = threading.Lock()
# send the queued commands to WJMX # send the queued commands to WJMX
def refresh(self): def refresh(self):
if not self.ser or self.ser is None: if not self.ser or self.ser is None:
@@ -281,9 +287,9 @@ class WJSendPlugin(ActionsPlugin, SequencePlugin, DisplayPlugin, ModulationRecei
with self.queue_lock: with self.queue_lock:
for queue, command in sorted(self.queue.items()): for queue, command in sorted(self.queue.items()):
self.send_buffered(queue, command[0], command[1]) self.send_buffered(queue, command[0], command[1])
#self.queue.clear() # self.queue.clear()
except Exception: except Exception:
print ("WJSendPlugin>>> !!! CAUGHT EXCEPTION running queue %s!!!" % queue) print("WJSendPlugin>>> !!! CAUGHT EXCEPTION running queue %s!!!" % queue)
import traceback import traceback
print(traceback.format_exc()) print(traceback.format_exc())
finally: finally:
@@ -294,61 +300,62 @@ class WJSendPlugin(ActionsPlugin, SequencePlugin, DisplayPlugin, ModulationRecei
self.pc.shaders.root.after(self.THROTTLE, self.refresh) self.pc.shaders.root.after(self.THROTTLE, self.refresh)
def send(self, queue, form, args): def send(self, queue, form, args):
#self.send_buffered(queue,output) # self.send_buffered(queue,output)
with self.queue_lock: with self.queue_lock:
self.queue[queue] = (form, args) #output self.queue[queue] = (form, args) # output
last = {} last = {}
last_modulated = {} last_modulated = {}
def send_buffered(self, queue, form, args, record = True):
def send_buffered(self, queue, form, args, record=True):
# only send if new command is different to the last one we sent # 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) mod_args = self.modulate_arguments(self.command_by_queue.get(queue), args)
if self.last_modulated.get(queue)!=(form,mod_args): if self.last_modulated.get(queue) != (form, mod_args):
#print("WJSendPlugin>> send_buffered attempting to parse queue\t%s with form\t'%s' and args\t%s" % (queue, form, args)) # print("WJSendPlugin>> send_buffered attempting to parse queue\t%s with form\t'%s' and args\t%s" % (queue, form, args))
# TODO: actually output modulated version of args # TODO: actually output modulated version of args
output = form.format(*mod_args) output = form.format(*mod_args)
self.send_serial_string(output) self.send_serial_string(output)
else: 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[queue] = (form, args)
self.last_modulated[queue] = (form,mod_args) self.last_modulated[queue] = (form, mod_args)
if self.last[queue]!=(form,args) and record: if self.last[queue] != (form, args) and record:
self.last_record[queue] = (form,args) self.last_record[queue] = (form, args)
else: else:
pass pass
#print("WJSendPlugin>> found no difference between:\n\t%s\n\t%s\n?" % (self.last_modulated.get(queue), (form,mod_args))) # print("WJSendPlugin>> found no difference between:\n\t%s\n\t%s\n?" % (self.last_modulated.get(queue), (form,mod_args)))
def send_append(self, command, value): def send_append(self, command, value):
# append value to the command as a hex value - for sending commands that aren't preprogrammed # append value to the command as a hex value - for sending commands that aren't preprogrammed
self.send(command.split(':')[0], "{}{:02X}", [ command, int(255*value) ]) self.send(command.split(':')[0], "{}{:02X}", [command, int(255 * value)])
def send_append_pad(self, pad, command, value): def send_append_pad(self, pad, command, value):
# append value, padded to length - for sending commands that aren't preprogrammed # append value, padded to length - for sending commands that aren't preprogrammed
self.send(command.split(':')[0], "{}{:0%iX}"%pad, [ command, int(255*value) ]) self.send(command.split(':')[0], "{}{:0%iX}" % pad, [command, int(255 * value)])
# methods for ActionPlugin - preprogrammed parameters # methods for ActionPlugin - preprogrammed parameters
@property @property
def parserlist(self): def parserlist(self):
return [ return [
( r"^open_serial$", self.open_serial ), (r"^open_serial$", self.open_serial),
( r"^wj_send_serial:([0-9a-zA-Z:]*)$", self.send_serial_string ), (r"^wj_send_serial:([0-9a-zA-Z:]*)$", self.send_serial_string),
#( r"^wj_set_colour:([A|B|T])_([x|y])$", self.set_colour ), # ( r"^wj_set_colour:([A|B|T])_([x|y])$", self.set_colour ),
#( r"^wj_set_back_colour:([x|y|z])$", self.set_back_colour ), # ( r"^wj_set_back_colour:([x|y|z])$", self.set_back_colour ),
#( r"^wj_set_position:([N|L])_([x|y])$", self.set_position ), # ( r"^wj_set_position:([N|L])_([x|y])$", self.set_position ),
#( r"^wj_set_mix$", self.set_mix ), # ( r"^wj_set_mix$", self.set_mix ),
( r"^wj_set_modulation_([a-zA-Z_]*)[:]?([a-zA-Z_]*)_slot_([0-3])_level$", self.set_modulation_command_argument_level), (r"^wj_set_modulation_([a-zA-Z_]*)[:]?([a-zA-Z_]*)_slot_([0-3])_level$", self.set_modulation_command_argument_level),
( r"^wj_set_current_modulation_slot_([0-3])_level$", self.set_current_modulation_level ), (r"^wj_set_current_modulation_slot_([0-3])_level$", self.set_current_modulation_level),
( r"^wj_send_append_pad:([0-9]*)_([[:0-9a-zA-Z]*)$", self.send_append_pad ), (r"^wj_send_append_pad:([0-9]*)_([[:0-9a-zA-Z]*)$", self.send_append_pad),
( r"^wj_send_append:([:0-9a-zA-Z]*)$", self.send_append ), (r"^wj_send_append:([:0-9a-zA-Z]*)$", self.send_append),
( r"^wj_set_([a-zA-Z_]*)[:]?([a-zA-Z_]*)$", self.catch_all ), (r"^wj_set_([a-zA-Z_]*)[:]?([a-zA-Z_]*)$", self.catch_all),
( r"^wj_select_next_command$", self.select_next_command ), (r"^wj_select_next_command$", self.select_next_command),
( r"^wj_select_previous_command$", self.select_previous_command ), (r"^wj_select_previous_command$", self.select_previous_command),
( r"^wj_select_next_argument$", self.select_next_argument ), (r"^wj_select_next_argument$", self.select_next_argument),
( r"^wj_select_previous_argument$", self.select_previous_argument ), (r"^wj_select_previous_argument$", self.select_previous_argument),
( r"^wj_reset_modulation$", self.reset_modulation_levels ), (r"^wj_reset_modulation$", self.reset_modulation_levels),
( r"^wj_toggle_active$", self.toggle_active ) (r"^wj_toggle_active$", self.toggle_active)
] ]
def toggle_active(self): def toggle_active(self):
@@ -357,29 +364,31 @@ class WJSendPlugin(ActionsPlugin, SequencePlugin, DisplayPlugin, ModulationRecei
self.asyncwriter = None self.asyncwriter = None
def reset_modulation_levels(self): def reset_modulation_levels(self):
for cmd,struct in self.commands.items(): for cmd, struct in self.commands.items():
struct['modulation'] = [{},{},{},{}] struct['modulation'] = [{}, {}, {}, {}]
def set_modulation_command_argument_level(self, command_name, argument_name, slot, level): 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 self.DEBUG:
if not argument_name: self.commands[command_name]['arg_names'][0] #argument_name = 'v' 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 self.commands[command_name].setdefault('modulation', [{}, {}, {}, {}])[slot][argument_name] = level
def set_current_modulation_level(self, slot, level): def set_current_modulation_level(self, slot, level):
self.set_modulation_command_argument_level(self.selected_command_name, self.commands[self.selected_command_name]['arg_names'][self.selected_argument_index], slot, level) self.set_modulation_command_argument_level(self.selected_command_name, self.commands[self.selected_command_name]['arg_names'][self.selected_argument_index], slot, level)
def select_previous_command(self): def select_previous_command(self):
selected_command_index = list(sorted(self.commands.keys())).index(self.selected_command_name)-1 selected_command_index = list(sorted(self.commands.keys())).index(self.selected_command_name) - 1
if selected_command_index<0: if selected_command_index < 0:
selected_command_index = len(self.commands.keys())-1 selected_command_index = len(self.commands.keys()) - 1
self.selected_command_name = sorted(list(self.commands.keys()))[selected_command_index] self.selected_command_name = sorted(list(self.commands.keys()))[selected_command_index]
self.selected_argument_index = 0 self.selected_argument_index = 0
def select_next_command(self): def select_next_command(self):
selected_command_index = list(sorted(self.commands.keys())).index(self.selected_command_name)+1 selected_command_index = list(sorted(self.commands.keys())).index(self.selected_command_name) + 1
if selected_command_index>=len(self.commands.keys()): if selected_command_index >= len(self.commands.keys()):
selected_command_index = 0 selected_command_index = 0
self.selected_command_name = sorted(list(self.commands.keys()))[selected_command_index] self.selected_command_name = sorted(list(self.commands.keys()))[selected_command_index]
@@ -387,44 +396,48 @@ class WJSendPlugin(ActionsPlugin, SequencePlugin, DisplayPlugin, ModulationRecei
def select_previous_argument(self): def select_previous_argument(self):
self.selected_argument_index -= 1 self.selected_argument_index -= 1
if self.selected_argument_index<0: if self.selected_argument_index < 0:
self.selected_argument_index = len(self.commands[self.selected_command_name]['arg_names'])-1 self.selected_argument_index = len(self.commands[self.selected_command_name]['arg_names']) - 1
def select_next_argument(self): def select_next_argument(self):
self.selected_argument_index += 1 self.selected_argument_index += 1
if self.selected_argument_index>=len(self.commands[self.selected_command_name]['arg_names']): if self.selected_argument_index >= len(self.commands[self.selected_command_name]['arg_names']):
self.selected_argument_index = 0 self.selected_argument_index = 0
def catch_all(self, param, argument_name, value): def catch_all(self, param, argument_name, value):
#print ("got catch-all %s, %s, %s" % (param, argument_name, value)) # print ("got catch-all %s, %s, %s" % (param, argument_name, value))
#arguments = packed_arguments.split("_") + [ value ] # arguments = packed_arguments.split("_") + [ value ]
#print("commands looks like %s" % self.commands) # print("commands looks like %s" % self.commands)
msg = self.commands[param] msg = self.commands[param]
if len(msg['arg_names'])==1: argument_name = msg['arg_names'][0] if len(msg['arg_names']) == 1:
msg['arguments'][argument_name] = int(value*255) # = arguments argument_name = msg['arg_names'][0]
self.send(msg['queue'], msg['form'], [ msg['arguments'][p] for p in msg['arg_names'] ] ) msg['arguments'][argument_name] = int(value * 255) # = arguments
self.send(msg['queue'], msg['form'], [msg['arguments'][p] for p in msg['arg_names']])
def modulate_arguments(self, command, args): def modulate_arguments(self, command, args):
args = args.copy() args = args.copy()
#if self.DEBUG: print("modulate_arguments passed %s and\n\t%s" % (command,args)) # if self.DEBUG: print("modulate_arguments passed %s and\n\t%s" % (command,args))
# TODO: rewrite this so that it combines multiple inputs and averages them # TODO: rewrite this so that it combines multiple inputs and averages them
for slot in range(0,4): for slot in range(0, 4):
modlevels = command.get('modulation',[{},{},{},{}])[slot] modlevels = command.get('modulation', [{}, {}, {}, {}])[slot]
#if self.DEBUG: print("\tfor modulate_arguments for slot %s got modlevels: %s" % (slot, modlevels)) # if self.DEBUG: print("\tfor modulate_arguments for slot %s got modlevels: %s" % (slot, modlevels))
#for i,m in enumerate(modlevels.values()): # for i,m in enumerate(modlevels.values()):
for arg_name,m in modlevels.items(): for arg_name, m in modlevels.items():
if m>0.0: if m > 0.0:
arg_index = command.get('arg_names').index(arg_name) 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 # amount, value, level
newvalue = self.pc.shaders.get_modulation_value( newvalue = self.pc.shaders.get_modulation_value(
args[arg_index]/255.0, args[arg_index] / 255.0,
self.modulation_value[slot], self.modulation_value[slot],
m m
) )
if self.DEBUG: print("\t\tnewvalue is %s" %newvalue) if self.DEBUG:
args[arg_index] = int(255*newvalue) print("\t\tnewvalue is %s" % newvalue)
if self.DEBUG: print("modulate_arguments returning:\n\t%s" % args) args[arg_index] = int(255 * newvalue)
if self.DEBUG:
print("modulate_arguments returning:\n\t%s" % args)
return args return args
# panasonic parameters are 8 bit so go 0-255, so 127 is default of centre value # panasonic parameters are 8 bit so go 0-255, so 127 is default of centre value
@@ -433,45 +446,44 @@ class WJSendPlugin(ActionsPlugin, SequencePlugin, DisplayPlugin, ModulationRecei
'name': 'Colour Corrector gain (both)', 'name': 'Colour Corrector gain (both)',
'queue': 'VCG', 'queue': 'VCG',
'form': 'VCG:T{:02X}', 'form': 'VCG:T{:02X}',
'arg_names': [ 'v' ], 'arg_names': ['v'],
'arguments': { 'v': 127 } 'arguments': {'v': 127}
}, },
'colour_T': { 'colour_T': {
'name': 'Colour Corrector (both)', 'name': 'Colour Corrector (both)',
'queue': 'VCC', 'queue': 'VCC',
'form': 'VCC:T{:02X}{:02X}', 'form': 'VCC:T{:02X}{:02X}',
'arg_names': [ 'x', 'y' ], 'arg_names': ['x', 'y'],
'arguments': { 'x': 127, 'y': 127 }, 'arguments': {'x': 127, 'y': 127},
}, },
'mix': { 'mix': {
'name': 'Mix/wipe', 'name': 'Mix/wipe',
'queue': 'VMM', 'queue': 'VMM',
'form': 'VMM:{:02X}', 'form': 'VMM:{:02X}',
'arg_names': [ 'v' ], 'arg_names': ['v'],
'arguments': { 'v': 127 }, 'arguments': {'v': 127},
}, },
'back_colour': { 'back_colour': {
'name': 'Matte colour HSV', 'name': 'Matte colour HSV',
'queue': 'VBM', 'queue': 'VBM',
'form': 'VBM:{:02X}{:02X}{:02X}', 'form': 'VBM:{:02X}{:02X}{:02X}',
'arg_names': [ 'h', 's', 'v' ], 'arg_names': ['h', 's', 'v'],
'arguments': { 'h': 127, 's': 127, 'v': 127 }, 'arguments': {'h': 127, 's': 127, 'v': 127},
}, },
'position_N': { 'position_N': {
'name': 'Positioner joystick XY', 'name': 'Positioner joystick XY',
'queue': 'VPS', 'queue': 'VPS',
'form': 'VPS:N{:02X}{:02X}', 'form': 'VPS:N{:02X}{:02X}',
'arg_names': [ 'y', 'x' ], 'arg_names': ['y', 'x'],
'arguments': { 'y': 127, 'x': 127 } 'arguments': {'y': 127, 'x': 127}
}, },
#'dsk_slice': { ## cant seem to find the right control code for this?! # 'dsk_slice': { ## cant seem to find the right control code for this?!
# 'name': 'Downstream Key Slice,Slope', # 'name': 'Downstream Key Slice,Slope',
# 'queue': 'VDS', # 'queue': 'VDS',
# 'form': 'VDS:{:02X}{:01X}', # 'form': 'VDS:{:02X}{:01X}',
# 'arg_names': [ 'slice','slope' ], # 'arg_names': [ 'slice','slope' ],
# 'arguments': { 'slice': 127, 'slope': 8 }, # 'arguments': { 'slice': 127, 'slope': 8 },
# 'modulation': [ {}, { 'slice': 1.0 }, {}, {} ] # 'modulation': [ {}, { 'slice': 1.0 }, {}, {} ]
#} # }
} }
command_by_queue = {} command_by_queue = {}

View File

@@ -1,36 +1,40 @@
import copy import copy
from json import JSONEncoder from json import JSONEncoder
def _default(self, obj): def _default(self, obj):
if getattr(obj.__class__,'to_json'): if getattr(obj.__class__, 'to_json'):
#return _default.default(obj.to_json()) # return _default.default(obj.to_json())
return obj.to_json() return obj.to_json()
else: else:
return _default.default(obj) return _default.default(obj)
_default.default = JSONEncoder().default _default.default = JSONEncoder().default
JSONEncoder.default = _default JSONEncoder.default = _default
class Frame: class Frame:
f = { 'shader_params': [[None]*4,[None]*4,[None]*4] } f = {'shader_params': [[None] * 4, [None] * 4, [None] * 4]}
pc = None pc = None
DEBUG_FRAMES = False#True DEBUG_FRAMES = False # True
def __init__(self, pc): def __init__(self, pc):
self.pc = pc self.pc = pc
def to_json(self): def to_json(self):
return self.f #{ 'f': self.f } return self.f # { 'f': self.f }
def get(self, key, default=None): def get(self, key, default=None):
return self.f.get(key,default) return self.f.get(key, default)
def has(self, key): def has(self, key):
return self.get(key) is not None return self.get(key) is not None
def store_live(self): def store_live(self):
frame = { frame = {
#'selected_shader_slots': [ shader.get('slot',None) for shader in self.pc.shaders.selected_shader_list ], # 'selected_shader_slots': [ shader.get('slot',None) for shader in self.pc.shaders.selected_shader_list ],
'selected_shader': copy.deepcopy(self.pc.shaders.selected_shader_list), 'selected_shader': copy.deepcopy(self.pc.shaders.selected_shader_list),
'shader_params': copy.deepcopy(self.pc.shaders.selected_param_list), 'shader_params': copy.deepcopy(self.pc.shaders.selected_param_list),
'layer_active_status': copy.deepcopy(self.pc.shaders.selected_status_list), 'layer_active_status': copy.deepcopy(self.pc.shaders.selected_status_list),
@@ -40,16 +44,16 @@ class Frame:
'strobe_amount': self.pc.shaders.data.settings['shader']['STROBE_AMOUNT']['value'] / 10.0, 'strobe_amount': self.pc.shaders.data.settings['shader']['STROBE_AMOUNT']['value'] / 10.0,
'shader_modulation_levels': copy.deepcopy(self.pc.shaders.modulation_level) 'shader_modulation_levels': copy.deepcopy(self.pc.shaders.modulation_level)
} }
#print("about to call get_plugin_frame_data") # print("about to call get_plugin_frame_data")
frame.update(self.pc.fm.get_plugin_frame_data()) frame.update(self.pc.fm.get_plugin_frame_data())
self.f = frame self.f = frame
#print("built frame: %s" % self.f) # print("built frame: %s" % self.f)
return self return self
def store_copy(self, f): def store_copy(self, f):
#print("told to store_copy %s" % f) # print("told to store_copy %s" % f)
if f is not None: if f is not None:
if f.get('f') is not None: #isinstance(f, Frame): if f.get('f') is not None: # isinstance(f, Frame):
f = f.get('f') f = f.get('f')
return self.store_copy(f.get('f')) return self.store_copy(f.get('f'))
self.f = f self.f = f
@@ -60,11 +64,11 @@ class Frame:
def get_active_shader_names(self): def get_active_shader_names(self):
s = "" s = ""
if self.has('selected_shader_slots'): if self.has('selected_shader_slots'):
return ['-']*3 return ['-'] * 3
if self.has('selected_shader'): if self.has('selected_shader'):
return [ shader['name'].strip() for shader in self.get('selected_shader') ] return [shader['name'].strip() for shader in self.get('selected_shader')]
return [ self.pc.data.shader_bank_data[layer][x].get('name').strip() if x is not None else '-'\ return [self.pc.data.shader_bank_data[layer][x].get('name').strip() if x is not None else '-' \
for layer,x in enumerate(self.get('selected_shader_slots',[None]*3)) for layer, x in enumerate(self.get('selected_shader_slots', [None] * 3))
] ]
def get_frame_summary(self): def get_frame_summary(self):
@@ -73,18 +77,18 @@ class Frame:
# list the recorded shader info in compact format # list the recorded shader info in compact format
names = self.get_active_shader_names() names = self.get_active_shader_names()
for layer in range(0,3): # number of shader layers for layer in range(0, 3): # number of shader layers
s = self.get_shader_layer_summary(layer) s = self.get_shader_layer_summary(layer)
summary.append(s) summary.append(s)
# handle summarising the rest of the recorded shader info, two-to-a-line where possible # handle summarising the rest of the recorded shader info, two-to-a-line where possible
count = 0 count = 0
line = "" line = ""
for key,d in sorted(self.f.items()): for key, d in sorted(self.f.items()):
#print ("get_frame_summary: checking %s value %s" % (key,d)) # print ("get_frame_summary: checking %s value %s" % (key,d))
if type(d) is dict and len(d)==0: # skip empty dicts if type(d) is dict and len(d) == 0: # skip empty dicts
continue continue
if key in ["selected_shader","layer_active_status","shader_params","shader_speeds","selected_shader_slots"]: if key in ["selected_shader", "layer_active_status", "shader_params", "shader_speeds", "selected_shader_slots"]:
# skip these as dealt with below # skip these as dealt with below
pass pass
elif key in ['shader_modulation_levels']: elif key in ['shader_modulation_levels']:
@@ -92,11 +96,11 @@ class Frame:
o = "" o = ""
for slot in range(4): for slot in range(4):
sl = self.pc.display.get_mod_slot_label(slot) sl = self.pc.display.get_mod_slot_label(slot)
o+= sl + "[" o += sl + "["
for param in range(4): for param in range(4):
o += self.pc.display.get_bar(d[layer][param][slot]) o += self.pc.display.get_bar(d[layer][param][slot])
o+= "] " o += "] "
summary.append("Shader layer %s: %s"%(layer,o)) summary.append("Shader layer %s: %s" % (layer, o))
elif self.pc.get_plugin_for_class_name(key) is not None: elif self.pc.get_plugin_for_class_name(key) is not None:
summary.append(self.pc.get_plugin_for_class_name(key).get_frame_summary(d)) summary.append(self.pc.get_plugin_for_class_name(key).get_frame_summary(d))
"""elif key in ["WJSendPlugin"]: """elif key in ["WJSendPlugin"]:
@@ -105,16 +109,16 @@ class Frame:
else: else:
line += "%s: %s" % (key, d) line += "%s: %s" % (key, d)
count += 1 count += 1
if count%2==1: if count % 2 == 1:
line += "\t" line += "\t"
elif count>0 and count%2==0: elif count > 0 and count % 2 == 0:
summary.append(line) summary.append(line)
line = "" line = ""
if line != "": if line != "":
summary.append(line) summary.append(line)
# add 'not shown' items # add 'not shown' items
if len(not_shown)>0: if len(not_shown) > 0:
summary.append(','.join(not_shown.keys())) summary.append(','.join(not_shown.keys()))
return summary return summary
@@ -122,28 +126,26 @@ class Frame:
def get_shader_layer_summary(self, layer): def get_shader_layer_summary(self, layer):
s = "%s%s" % (layer, " " if layer != self.pc.data.shader_layer else ">") s = "%s%s" % (layer, " " if layer != self.pc.data.shader_layer else ">")
s += "[" s += "["
s += self.pc.display.get_compact_indicators([\ s += self.pc.display.get_compact_indicators([ \
(i==self.get('selected_shader_slots',[-1]*3)[layer]) or\ (i == self.get('selected_shader_slots', [-1] * 3)[layer]) or \
(self.has('selected_shader') and self.pc.data.shader_bank_data[layer][i]['name'] == self.get('selected_shader')[layer]['name'])\ (self.has('selected_shader') and self.pc.data.shader_bank_data[layer][i]['name'] == self.get('selected_shader')[layer]['name']) \
for i in range(10)\ for i in range(10) \
]) ])
s += "]" s += "]"
if self.has('layer_active_status'): if self.has('layer_active_status'):
s += " %s " % (self.get('layer_active_status',['-']*3)[layer]) s += " %s " % (self.get('layer_active_status', ['-'] * 3)[layer])
if self.get('selected_shader'): if self.get('selected_shader'):
s += "{:14.14}".format(self.get('selected_shader')[layer].get('name').replace('.frag','').strip()) s += "{:14.14}".format(self.get('selected_shader')[layer].get('name').replace('.frag', '').strip())
s += " " + self.get_shader_param_summary(layer) + " " s += " " + self.get_shader_param_summary(layer) + " "
if self.has('shader_speeds'): if self.has('shader_speeds'):
s += self.pc.display.get_speed_indicator(self.get('shader_speeds',[0.0]*3)[layer]) s += self.pc.display.get_speed_indicator(self.get('shader_speeds', [0.0] * 3)[layer])
return s return s
def get_shader_param_summary(self, layer): def get_shader_param_summary(self, layer):
if self.get('shader_params') is None: if self.get('shader_params') is None:
return "" return ""
@@ -169,7 +171,7 @@ class Frame:
elif preset.has('selected_shader') and preset.get('selected_shader')[layer] is not None: elif preset.has('selected_shader') and preset.get('selected_shader')[layer] is not None:
# match selected shader to a slot and call that back if it exists # match selected shader to a slot and call that back if it exists
found = False found = False
for slot,shader in enumerate(self.pc.data.shader_bank_data[layer]): for slot, shader in enumerate(self.pc.data.shader_bank_data[layer]):
if shader['name'] == preset.get('selected_shader')[layer]['name']: if shader['name'] == preset.get('selected_shader')[layer]['name']:
self.pc.actions.call_method_name('play_shader_%s_%s' % (layer, slot)) self.pc.actions.call_method_name('play_shader_%s_%s' % (layer, slot))
found = True found = True
@@ -185,40 +187,40 @@ class Frame:
level = preset.get('shader_modulation_levels')[layer][param][slot] level = preset.get('shader_modulation_levels')[layer][param][slot]
self.pc.shaders.set_param_layer_slot_modulation_level(param, layer, slot, level) self.pc.shaders.set_param_layer_slot_modulation_level(param, layer, slot, level)
for (layer, active) in enumerate(preset.get('layer_active_status',[])): for (layer, active) in enumerate(preset.get('layer_active_status', [])):
# print ("got %s layer with status %s " % (layer,active)) # print ("got %s layer with status %s " % (layer,active))
if active=='': if active == '':
self.pc.actions.call_method_name('start_shader_layer_%s' % layer) self.pc.actions.call_method_name('start_shader_layer_%s' % layer)
else: else:
self.pc.actions.call_method_name('stop_shader_layer_%s' % layer) self.pc.actions.call_method_name('stop_shader_layer_%s' % layer)
def recall_frame_params(self): def recall_frame_params(self):
#print("recall_frame_params got: %s" % preset.get('shader_params')) # print("recall_frame_params got: %s" % preset.get('shader_params'))
for (layer, param_list) in enumerate(self.get('shader_params',[])): for (layer, param_list) in enumerate(self.get('shader_params', [])):
if param_list: if param_list:
for param,value in enumerate(param_list): for param, value in enumerate(param_list):
#if (ignored is not None and ignored['shader_params'][layer][param] is not None): # if (ignored is not None and ignored['shader_params'][layer][param] is not None):
# print ("ignoring %s,%s because value is %s" % (layer,param,ignored['shader_params'][layer][param])) # print ("ignoring %s,%s because value is %s" % (layer,param,ignored['shader_params'][layer][param]))
# continue # continue
if (value is not None): if (value is not None):
#print("recalling layer %s param %s: value %s" % (layer,param,value)) # print("recalling layer %s param %s: value %s" % (layer,param,value))
self.pc.actions.call_method_name('set_the_shader_param_%s_layer_%s_continuous' % (param,layer), value) self.pc.actions.call_method_name('set_the_shader_param_%s_layer_%s_continuous' % (param, layer), value)
if self.has('feedback_active'): if self.has('feedback_active'):
self.pc.data.feedback_active = self.get('feedback_active',self.pc.data.feedback_active) self.pc.data.feedback_active = self.get('feedback_active', self.pc.data.feedback_active)
if self.pc.data.feedback_active: if self.pc.data.feedback_active:
self.pc.actions.call_method_name('enable_feedback') self.pc.actions.call_method_name('enable_feedback')
else: else:
self.pc.actions.call_method_name('disable_feedback') self.pc.actions.call_method_name('disable_feedback')
if self.has('x3_as_speed'): if self.has('x3_as_speed'):
self.pc.data.settings['shader']['X3_AS_SPEED']['value'] = self.get('x3_as_speed',self.pc.data.settings['shader']['X3_AS_SPEED']['value']) self.pc.data.settings['shader']['X3_AS_SPEED']['value'] = self.get('x3_as_speed', self.pc.data.settings['shader']['X3_AS_SPEED']['value'])
"""if self.data.settings['shader']['X3_AS_SPEED']['value']: """if self.data.settings['shader']['X3_AS_SPEED']['value']:
self.data.plugins.actions.call_method_name('enable_x3_as_speed') self.data.plugins.actions.call_method_name('enable_x3_as_speed')
else: else:
self.data.plugins.actions.call_method_name('disable_x3_as_speed')""" self.data.plugins.actions.call_method_name('disable_x3_as_speed')"""
for (layer, speed) in enumerate(self.get('shader_speeds',[])): for (layer, speed) in enumerate(self.get('shader_speeds', [])):
if speed is not None: if speed is not None:
self.pc.actions.call_method_name('set_shader_speed_layer_%s_amount' % layer, speed) self.pc.actions.call_method_name('set_shader_speed_layer_%s_amount' % layer, speed)
@@ -227,19 +229,19 @@ class Frame:
from data_centre.plugin_collection import AutomationSourcePlugin from data_centre.plugin_collection import AutomationSourcePlugin
for plugin in self.pc.get_plugins(AutomationSourcePlugin): for plugin in self.pc.get_plugins(AutomationSourcePlugin):
#print("recalling for plugin %s with data %s" % (plugin, self.get(plugin.frame_key))) # print("recalling for plugin %s with data %s" % (plugin, self.get(plugin.frame_key)))
plugin.recall_frame_data(self.get(plugin.frame_key)) plugin.recall_frame_data(self.get(plugin.frame_key))
def merge(self, frame2): def merge(self, frame2):
from copy import deepcopy from copy import deepcopy
f = deepcopy(self.f) #frame1.copy() f = deepcopy(self.f) # frame1.copy()
#if self.DEBUG_FRAMES: print("merge_frames: got frame1\t%s" % frame1) # if self.DEBUG_FRAMES: print("merge_frames: got frame1\t%s" % frame1)
#if self.DEBUG_FRAMES: print("merge_frames: got frame2\t%s" % frame2) # if self.DEBUG_FRAMES: print("merge_frames: got frame2\t%s" % frame2)
for i,f2 in enumerate(frame2.get('shader_params')): for i, f2 in enumerate(frame2.get('shader_params')):
for i2,p in enumerate(f2): for i2, p in enumerate(f2):
if p is not None: if p is not None:
if 'shader_params' not in f: if 'shader_params' not in f:
f['shader_params'] = [[None]*4,[None]*4,[None]*4] f['shader_params'] = [[None] * 4, [None] * 4, [None] * 4]
f['shader_params'][i][i2] = p f['shader_params'][i][i2] = p
if frame2.has('feedback_active'): if frame2.has('feedback_active'):
@@ -252,7 +254,7 @@ class Frame:
if 'shader_speeds' in frame2.f: if 'shader_speeds' in frame2.f:
f['shader_speeds'] = frame2.get('shader_speeds') f['shader_speeds'] = frame2.get('shader_speeds')
else: else:
for i,s in enumerate(frame2.get('shader_speeds')): for i, s in enumerate(frame2.get('shader_speeds')):
if s is not None: if s is not None:
f['shader_speeds'][i] = s f['shader_speeds'][i] = s
@@ -261,19 +263,21 @@ class Frame:
from data_centre.plugin_collection import AutomationSourcePlugin from data_centre.plugin_collection import AutomationSourcePlugin
for plugin in self.pc.get_plugins(AutomationSourcePlugin): 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)) 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) return Frame(self.pc).store_copy(f)
def get_ignored(self, ignored): def get_ignored(self, ignored):
from copy import deepcopy from copy import deepcopy
f = deepcopy(self.f) #frame1.copy() f = deepcopy(self.f) # frame1.copy()
frame = self.f frame = self.f
ignored = ignored.f ignored = ignored.f
if self.DEBUG_FRAMES: print("get_frame_ignored: got frame\t%s" % self.f) if self.DEBUG_FRAMES:
for i,f2 in enumerate(frame.get('shader_params',[])): print("get_frame_ignored: got frame\t%s" % self.f)
for i2,p in enumerate(f2): for i, f2 in enumerate(frame.get('shader_params', [])):
for i2, p in enumerate(f2):
if ignored['shader_params'][i][i2] is not None: if ignored['shader_params'][i][i2] is not None:
f['shader_params'][i][i2] = None f['shader_params'][i][i2] = None
if 'feedback_active' in ignored: if 'feedback_active' in ignored:
@@ -281,7 +285,7 @@ class Frame:
if 'x3_as_speed' in ignored: if 'x3_as_speed' in ignored:
f['x3_as_speed'] = None f['x3_as_speed'] = None
if 'shader_speeds' in ignored and 'shader_speeds' in frame: if 'shader_speeds' in ignored and 'shader_speeds' in frame:
for i,s in enumerate(frame.get('shader_speeds')): for i, s in enumerate(frame.get('shader_speeds')):
if ignored['shader_speeds'][i] is not None: if ignored['shader_speeds'][i] is not None:
f['shader_speeds'][i] = None f['shader_speeds'][i] = None
if 'strobe_amount' in ignored: if 'strobe_amount' in ignored:
@@ -290,17 +294,19 @@ class Frame:
from data_centre.plugin_collection import AutomationSourcePlugin from data_centre.plugin_collection import AutomationSourcePlugin
for plugin in self.pc.get_plugins(AutomationSourcePlugin): for plugin in self.pc.get_plugins(AutomationSourcePlugin):
if ignored.get(plugin.frame_key) is not None: if ignored.get(plugin.frame_key) is not None:
#print("ignoring for %s:\n\t%s\n" % (plugin.frame_key, ignored.get(plugin.frame_key))) # 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,{})) 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) return Frame(self.pc).store_copy(f)
def is_empty(self): def is_empty(self):
#from copy import deepcopy # from copy import deepcopy
#f = deepcopy(frame) #frame1.copy() # f = deepcopy(frame) #frame1.copy()
frame = self.f 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'): if self.has('feedback_active'):
return False return False
@@ -309,13 +315,13 @@ class Frame:
if self.has('strobe_amount'): if self.has('strobe_amount'):
return False return False
for i,f in enumerate(frame['shader_params']): for i, f in enumerate(frame['shader_params']):
for i2,p in enumerate(f): for i2, p in enumerate(f):
if p is not None: #ignored['shader_params'][i][i2] is not None: if p is not None: # ignored['shader_params'][i][i2] is not None:
return False return False
if self.has('shader_speeds'): if self.has('shader_speeds'):
for i,f in enumerate(frame['shader_speeds']): for i, f in enumerate(frame['shader_speeds']):
if f is not None: if f is not None:
return False return False
@@ -326,11 +332,12 @@ class Frame:
if not plugin.is_frame_data_empty(frame.get(plugin.frame_key)): if not plugin.is_frame_data_empty(frame.get(plugin.frame_key)):
return False 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 return True
def get_diff(self, current_frame): def get_diff(self, current_frame):
#if not last_frame: return current_frame # if not last_frame: return current_frame
current_frame = current_frame.f current_frame = current_frame.f
last_frame = self.f last_frame = self.f
@@ -339,12 +346,13 @@ class Frame:
print("last_frame: \t%s" % last_frame['shader_params']) print("last_frame: \t%s" % last_frame['shader_params'])
print("current_frame: \t%s" % current_frame['shader_params']) print("current_frame: \t%s" % current_frame['shader_params'])
param_values = [[None]*4,[None]*4,[None]*4] param_values = [[None] * 4, [None] * 4, [None] * 4]
for layer,params in enumerate(current_frame.get('shader_params',[[None]*4]*3)): for layer, params in enumerate(current_frame.get('shader_params', [[None] * 4] * 3)):
#if self.DEBUG_FRAMES: print("got layer %s params: %s" % (layer, params)) # if self.DEBUG_FRAMES: print("got layer %s params: %s" % (layer, params))
for param,p in enumerate(params): for param, p in enumerate(params):
if p is not None and p != last_frame.get('shader_params')[layer][param]: 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 param_values[layer][param] = p
if current_frame['feedback_active'] is not None and last_frame['feedback_active'] != current_frame['feedback_active']: if current_frame['feedback_active'] is not None and last_frame['feedback_active'] != current_frame['feedback_active']:
@@ -357,8 +365,8 @@ class Frame:
else: else:
x3_as_speed = None x3_as_speed = None
speed_values = [None]*3 speed_values = [None] * 3
for layer,param in enumerate(current_frame.get('shader_speeds',[None]*3)): for layer, param in enumerate(current_frame.get('shader_speeds', [None] * 3)):
if param is not None and param != last_frame['shader_speeds'][layer]: if param is not None and param != last_frame['shader_speeds'][layer]:
speed_values[layer] = param speed_values[layer] = param
@@ -385,14 +393,12 @@ class Frame:
'strobe_amount': strobe_amount, 'strobe_amount': strobe_amount,
} }
diff.update(plugin_data) 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) return Frame(self.pc).store_copy(diff)
class FrameManager: class FrameManager:
pc = None pc = None
@@ -430,9 +436,9 @@ class FrameManager:
from data_centre.plugin_collection import AutomationSourcePlugin from data_centre.plugin_collection import AutomationSourcePlugin
for plugin in self.pc.get_plugins(AutomationSourcePlugin): for plugin in self.pc.get_plugins(AutomationSourcePlugin):
data[plugin.frame_key] = plugin.get_frame_data() data[plugin.frame_key] = plugin.get_frame_data()
#plugin.clear_recorded_frame() # plugin.clear_recorded_frame()
#print("get_plugin_frame_data looks like %s" % data) # print("get_plugin_frame_data looks like %s" % data)
return data return data
def interpolate_clip(self, frames): def interpolate_clip(self, frames):
@@ -444,9 +450,9 @@ class FrameManager:
# else, # else,
# store as last value # store as last value
print("got pre-interpolated clip: %s" % [ f.f for f in frames if f is not None]) print("got pre-interpolated clip: %s" % [f.f for f in frames if f is not None])
last = [ [None]*4, [None]*4, [None]*4 ] last = [[None] * 4, [None] * 4, [None] * 4]
"""for findex,frame in enumerate(frames): """for findex,frame in enumerate(frames):
if frame is None: if frame is None:
@@ -455,18 +461,18 @@ class FrameManager:
reproc_to = 0 reproc_to = 0
def process(self, findex, frame): def process(self, findex, frame):
for layer,params in enumerate(frame.get('shader_params',[])): for layer, params in enumerate(frame.get('shader_params', [])):
for param,value in enumerate(params): for param, value in enumerate(params):
if value is None and last[layer][param] is not None: if value is None and last[layer][param] is not None:
# find distance to when this value changes again # find distance to when this value changes again
gap,future_value = self.get_distance_value_layer_param(frames,findex,layer,param) gap, future_value = self.get_distance_value_layer_param(frames, findex, layer, param)
if gap==0 or future_value==value: # if doesnt change again, do nothing if gap == 0 or future_value == value: # if doesnt change again, do nothing
continue continue
newvalue = self.interpolate(last[layer][param], future_value, gap) newvalue = self.interpolate(last[layer][param], future_value, gap)
params[param] = newvalue params[param] = newvalue
print("findex %s: updating interpolated value to %s - should be between %s and %s over gap %s" % (findex, newvalue, last[layer][param], future_value, gap)) print("findex %s: updating interpolated value to %s - should be between %s and %s over gap %s" % (findex, newvalue, last[layer][param], future_value, gap))
last[layer][param] = newvalue last[layer][param] = newvalue
#elif last[layer][param] is None: # elif last[layer][param] is None:
# reproc_to = findex # reproc_to = findex
elif value is not None: elif value is not None:
last[layer][param] = value last[layer][param] = value
@@ -476,11 +482,11 @@ class FrameManager:
plugin.process_interpolate_clip(frames) plugin.process_interpolate_clip(frames)
for i in range(2): for i in range(2):
for findex,frame in enumerate(frames): for findex, frame in enumerate(frames):
if frame is None: if frame is None:
continue continue
process(self,findex,frame) process(self, findex, frame)
"""for findex in range(reproc_to): """for findex in range(reproc_to):
if frames[findex] is None: if frames[findex] is None:
@@ -488,23 +494,23 @@ class FrameManager:
process(self,findex,frames[findex])""" process(self,findex,frames[findex])"""
print("got interpolated clip: %s" % [ f.f for f in frames if f is not None ]) print("got interpolated clip: %s" % [f.f for f in frames if f is not None])
def get_distance_value_layer_param(self, frames, findex, layer, param): def get_distance_value_layer_param(self, frames, findex, layer, param):
for i in range(1,len(frames)): for i in range(1, len(frames)):
search_findex = i + findex search_findex = i + findex
search_findex %= len(frames) search_findex %= len(frames)
if frames[search_findex] is not None and frames[search_findex].get('shader_params',[ [None]*4, [None]*4, [None]*4 ])[layer][param] is not None: if frames[search_findex] is not None and frames[search_findex].get('shader_params', [[None] * 4, [None] * 4, [None] * 4])[layer][param] is not None:
return i, frames[search_findex].get('shader_params')[layer][param] return i, frames[search_findex].get('shader_params')[layer][param]
return 0, None return 0, None
def interpolate(self, value1, value2, total_steps): def interpolate(self, value1, value2, total_steps):
diff = max(value1,value2)-min(value1,value2) diff = max(value1, value2) - min(value1, value2)
sl = diff / total_steps sl = diff / total_steps
if value1>value2: if value1 > value2:
v = value1-sl v = value1 - sl
else: else:
v = value1+sl v = value1 + sl
print("interpolate between\t%s and\t%s over\t%s steps, got sl\t%s and value\t%s" % (value1,value2,total_steps, sl, v)) print("interpolate between\t%s and\t%s over\t%s steps, got sl\t%s and value\t%s" % (value1, value2, total_steps, sl, v))
return v return v

View File

@@ -29,6 +29,7 @@ message_handler = MessageHandler()
data = Data(message_handler) data = Data(message_handler)
def setup_osc_client(): def setup_osc_client():
client_parser = argparse.ArgumentParser() client_parser = argparse.ArgumentParser()
client_parser.add_argument("--ip", default="127.0.0.1", help="the ip") client_parser.add_argument("--ip", default="127.0.0.1", help="the ip")
@@ -38,10 +39,11 @@ def setup_osc_client():
return udp_client.SimpleUDPClient(client_args.ip, client_args.port) return udp_client.SimpleUDPClient(client_args.ip, client_args.port)
osc_client = setup_osc_client() osc_client = setup_osc_client()
# setup the video driver # setup the video driver
video_driver = VideoDriver(tk, osc_client, message_handler, data) video_driver = VideoDriver(tk, osc_client, message_handler, data)
#capture = Capture(tk, osc_client, message_handler, data) # capture = Capture(tk, osc_client, message_handler, data)
shaders = Shaders(tk, osc_client, message_handler, data) shaders = Shaders(tk, osc_client, message_handler, data)
# setup the display # setup the display
@@ -67,14 +69,12 @@ actions.toggle_x_autorepeat()
frame.pack() frame.pack()
tk.attributes("-fullscreen", True) tk.attributes("-fullscreen", True)
def handle_error(exc, val, tb): def handle_error(exc, val, tb):
print('traceback for error : {}'.format(traceback.format_exc())) print('traceback for error : {}'.format(traceback.format_exc()))
message_handler.set_message('ERROR', val, traceback.format_exc()) message_handler.set_message('ERROR', val, traceback.format_exc())
tk.report_callback_exception = handle_error tk.report_callback_exception = handle_error
tk.mainloop() tk.mainloop()

View File

@@ -1,5 +1,6 @@
import Adafruit_MCP3008 import Adafruit_MCP3008
class AnalogInput(object): class AnalogInput(object):
def __init__(self, root, message_handler, display, actions, data): def __init__(self, root, message_handler, display, actions, data):
self.root = root self.root = root
@@ -9,19 +10,18 @@ class AnalogInput(object):
self.data = data self.data = data
self.analog_mappings = data.analog_mappings self.analog_mappings = data.analog_mappings
self.analog_delay = 50 self.analog_delay = 50
self.last_readings = [0,0,0,0,0,0,0,0] self.last_readings = [0, 0, 0, 0, 0, 0, 0, 0]
self.analog_input = None self.analog_input = None
self.check_if_listening_enabled() self.check_if_listening_enabled()
def check_if_listening_enabled(self): def check_if_listening_enabled(self):
if self.data.settings['user_input']['ANALOG_INPUT']['value'] == 'enabled': if self.data.settings['user_input']['ANALOG_INPUT']['value'] == 'enabled':
if not self.analog_input: if not self.analog_input:
try: try:
## note - using software spi for now although on the same pins as the hardware spi described below because hardware spi wasnt working with lcd display ## note - using software spi for now although on the same pins as the hardware spi described below because hardware spi wasnt working with lcd display
#SPI_PORT = 1 # SPI_PORT = 1
#SPI_DEVICE = 2 # SPI_DEVICE = 2
#self.analog_input = Adafruit_MCP3008.MCP3008(spi=SPI.SpiDev(SPI_PORT, SPI_DEVICE)) # self.analog_input = Adafruit_MCP3008.MCP3008(spi=SPI.SpiDev(SPI_PORT, SPI_DEVICE))
CLK = 21 CLK = 21
MISO = 19 MISO = 19
MOSI = 20 MOSI = 20
@@ -37,12 +37,12 @@ class AnalogInput(object):
def poll_analog_inputs(self): def poll_analog_inputs(self):
if self.data.settings['user_input']['ANALOG_INPUT']['value'] == 'enabled': if self.data.settings['user_input']['ANALOG_INPUT']['value'] == 'enabled':
for i in range(0,8): for i in range(0, 8):
if str(i) in self.analog_mappings: if str(i) in self.analog_mappings:
this_reading = self.analog_input.read_adc(i) this_reading = self.analog_input.read_adc(i)
#print(str(this_reading)) # print(str(this_reading))
if abs(this_reading - self.last_readings[i]) > 10: if abs(this_reading - self.last_readings[i]) > 10:
#print('the diff is {}'.format(this_reading - self.last_readings[i])) # print('the diff is {}'.format(this_reading - self.last_readings[i]))
self.run_action_for_mapped_channel(i, this_reading) self.run_action_for_mapped_channel(i, this_reading)
self.last_readings[i] = this_reading self.last_readings[i] = this_reading
self.root.after(self.analog_delay, self.poll_analog_inputs) self.root.after(self.analog_delay, self.poll_analog_inputs)
@@ -69,14 +69,12 @@ class AnalogInput(object):
method_name = this_mapping[mode][0] method_name = this_mapping[mode][0]
if channel_value is not None: if channel_value is not None:
norm_channel_value = channel_value/1023 norm_channel_value = channel_value / 1023
else: else:
norm_channel_value = None norm_channel_value = None
print('the action being called is {}'.format(method_name)) print('the action being called is {}'.format(method_name))
self.actions.call_method_name(method_name, norm_channel_value) self.actions.call_method_name(method_name, norm_channel_value)
## not sure whether we want to update the screen in general; here - probably not most of the time ... ## not sure whether we want to update the screen in general; here - probably not most of the time ...
#if 'cc' not in message_name: # if 'cc' not in message_name:
# self.display.refresh_display() # self.display.refresh_display()

View File

@@ -18,10 +18,10 @@ class MidiInput(object):
self.try_open_port() self.try_open_port()
def try_open_port(self): def try_open_port(self):
#self.data.midi_status = 'disconnected' # self.data.midi_status = 'disconnected'
self.midi_setting = self.data.settings['user_input']['MIDI_INPUT']['value'] self.midi_setting = self.data.settings['user_input']['MIDI_INPUT']['value']
self.port_index = self.data.midi_port_index self.port_index = self.data.midi_port_index
#print('try open port : midi setting is {}'.format(midi_setting)) # print('try open port : midi setting is {}'.format(midi_setting))
if self.midi_setting == 'usb': if self.midi_setting == 'usb':
self.actions.stop_serial_port_process() self.actions.stop_serial_port_process()
self.open_this_port_and_start_listening('20') self.open_this_port_and_start_listening('20')
@@ -48,7 +48,7 @@ class MidiInput(object):
self.midi_mappings = self.data.load_midi_mapping_for_device(self.midi_device.name.split(":")[0]) self.midi_mappings = self.data.load_midi_mapping_for_device(self.midi_device.name.split(":")[0])
self.midi_output = self.find_output_plugin(midi_devices[subport_index]) self.midi_output = self.find_output_plugin(midi_devices[subport_index])
if self.midi_output: if self.midi_output:
#self.midi_feedback_device = mido.open_output(midi_device_on_port[subport_index]) # self.midi_feedback_device = mido.open_output(midi_device_on_port[subport_index])
self.root.after(self.midi_delay, self.refresh_midi_feedback) self.root.after(self.midi_delay, self.refresh_midi_feedback)
self.poll_midi_input() self.poll_midi_input()
elif self.data.midi_status == 'connected': elif self.data.midi_status == 'connected':
@@ -62,7 +62,7 @@ class MidiInput(object):
current_message_buffer = [i.dict() for i in self.midi_device.iter_pending()] current_message_buffer = [i.dict() for i in self.midi_device.iter_pending()]
refined_buffer = [] refined_buffer = []
#refine buffer from lastest messages first # refine buffer from lastest messages first
current_message_buffer.reverse() current_message_buffer.reverse()
for message in current_message_buffer: for message in current_message_buffer:
# discard notes from wrong channel # discard notes from wrong channel
@@ -81,7 +81,7 @@ class MidiInput(object):
for message in refined_buffer: for message in refined_buffer:
self.on_midi_message(message) self.on_midi_message(message)
#print('the number processed {}'.format(i)) # print('the number processed {}'.format(i))
if self.data.settings['user_input']['MIDI_INPUT']['value'] == self.midi_setting and self.data.midi_port_index == self.port_index: if self.data.settings['user_input']['MIDI_INPUT']['value'] == self.midi_setting and self.data.midi_port_index == self.port_index:
self.root.after(self.midi_delay, self.poll_midi_input) self.root.after(self.midi_delay, self.poll_midi_input)
else: else:
@@ -94,9 +94,9 @@ class MidiInput(object):
mapped_message_name = message_dict['type'] mapped_message_name = message_dict['type']
mapped_message_value = None mapped_message_value = None
if 'note' in message_dict: if 'note' in message_dict:
mapped_message_name = '{} {}'.format(mapped_message_name,message_dict['note']) mapped_message_name = '{} {}'.format(mapped_message_name, message_dict['note'])
if 'control' in message_dict: if 'control' in message_dict:
mapped_message_name = '{} {}'.format(mapped_message_name,message_dict['control']) mapped_message_name = '{} {}'.format(mapped_message_name, message_dict['control'])
mapped_message_value = message_dict['value'] mapped_message_value = message_dict['value']
if mapped_message_name in self.midi_mappings.keys(): if mapped_message_name in self.midi_mappings.keys():
@@ -119,14 +119,14 @@ class MidiInput(object):
if self.data.function_on and len(this_mapping[mode]) > 1: if self.data.function_on and len(this_mapping[mode]) > 1:
method_name = this_mapping[mode][1] method_name = this_mapping[mode][1]
#self.data.function_on = False # self.data.function_on = False
else: else:
method_name = this_mapping[mode][0] method_name = this_mapping[mode][0]
#print('[][][][][ in mode {}, the action being called is {} from message_name {} in control_mode {}' # print('[][][][][ in mode {}, the action being called is {} from message_name {} in control_mode {}'
# .format(mode, method_name, message_name, self.data.control_mode)) # .format(mode, method_name, message_name, self.data.control_mode))
if mapped_message_value is not None: if mapped_message_value is not None:
norm_message_value = mapped_message_value/127 norm_message_value = mapped_message_value / 127
else: else:
norm_message_value = None norm_message_value = None
@@ -135,7 +135,7 @@ class MidiInput(object):
## only update screen if not continuous - seeing if cc can respond faster if not refreshing screen on every action ## only update screen if not continuous - seeing if cc can respond faster if not refreshing screen on every action
if 'continuous' not in message_name: if 'continuous' not in message_name:
self.display.refresh_display() self.display.refresh_display()
#self.refresh_midi_feedback() # self.refresh_midi_feedback()
# Plugins to support MIDI feedback # Plugins to support MIDI feedback
@@ -143,16 +143,16 @@ class MidiInput(object):
# loop over the plugins # loop over the plugins
# find one that self.supports_midi_feedback(self.midi_device.name): # find one that self.supports_midi_feedback(self.midi_device.name):
# open the midi device self.midi_feedback_device = mido.open_output(midi_device_on_port[subport_index]) # open the midi device self.midi_feedback_device = mido.open_output(midi_device_on_port[subport_index])
print ("Looking for a MIDI Feedback plugin that supports %s..." % midi_device) print("Looking for a MIDI Feedback plugin that supports %s..." % midi_device)
from data_centre.plugin_collection import MidiFeedbackPlugin from data_centre.plugin_collection import MidiFeedbackPlugin
for p in self.data.plugins.get_plugins(MidiFeedbackPlugin): for p in self.data.plugins.get_plugins(MidiFeedbackPlugin):
if p.supports_midi_feedback(midi_device): if p.supports_midi_feedback(midi_device):
print ("Found one! Opening device") print("Found one! Opening device")
p.set_midi_device(mido.open_output(midi_device)) p.set_midi_device(mido.open_output(midi_device))
return p return p
print ("Didn't find one!") print("Didn't find one!")
def refresh_midi_feedback(self): def refresh_midi_feedback(self):
@@ -160,14 +160,12 @@ class MidiInput(object):
if self.midi_output and self.data.settings['user_input']['MIDI_INPUT']['value'] == self.midi_setting and self.data.midi_port_index == self.port_index: if self.midi_output and self.data.settings['user_input']['MIDI_INPUT']['value'] == self.midi_setting and self.data.midi_port_index == self.port_index:
if self.midi_output.supports_midi_feedback(self.data.midi_device_name): if self.midi_output.supports_midi_feedback(self.data.midi_device_name):
self.root.after(self.midi_delay*5, self.refresh_midi_feedback) self.root.after(self.midi_delay * 5, self.refresh_midi_feedback)
def find_binding_for_action(self, action): def find_binding_for_action(self, action):
for bind,a in self.midi_mappings.items(): for bind, a in self.midi_mappings.items():
#print("looped over %s : %s " % (bind,a)) # print("looped over %s : %s " % (bind,a))
for (b,c) in a.items(): for (b, c) in a.items():
if action in c: if action in c:
#print ("find_binding_for_action(%s) got %s" % (action, bind)) # print ("find_binding_for_action(%s) got %s" % (action, bind))
return bind return bind

View File

@@ -24,8 +24,8 @@ class NumpadInput(object):
numpad = list(string.ascii_lowercase[0:19]) numpad = list(string.ascii_lowercase[0:19])
if event.char is 'h': # DISP button if event.char is 'h': # DISP button
#self.root.after(60, lambda:self.on_key_press_delay(event.char)) # self.root.after(60, lambda:self.on_key_press_delay(event.char))
#return # return
if self.data.is_display_held: if self.data.is_display_held:
return # ignore spurious message if already held""" return # ignore spurious message if already held"""
self.data.is_display_held = True self.data.is_display_held = True
@@ -54,13 +54,13 @@ class NumpadInput(object):
##print ("--- releasing %s" % event.char) ##print ("--- releasing %s" % event.char)
# lag for 60ms to check that this is not a 'stream of 000' bullshit job from the keypad # lag for 60ms to check that this is not a 'stream of 000' bullshit job from the keypad
if event.char is 'h' and not self.in_0_event: if event.char is 'h' and not self.in_0_event:
self.root.after(self.KEY_000_DELAY+5, self.on_key_disp_release_delay) self.root.after(self.KEY_000_DELAY + 5, self.on_key_disp_release_delay)
#self.data.is_display_held = False # self.data.is_display_held = False
def on_mouse_move(self, event): def on_mouse_move(self, event):
if self.data.settings['user_input'].setdefault( if self.data.settings['user_input'].setdefault(
'MOUSE_INPUT', 'MOUSE_INPUT',
self.data.default_settings.get('MOUSE_INPUT',{'value': 'enabled'})).get('value') != 'enabled': self.data.default_settings.get('MOUSE_INPUT', {'value': 'enabled'})).get('value') != 'enabled':
return return
if event.x > 480 or event.y > 320: if event.x > 480 or event.y > 320:
return return
@@ -69,13 +69,13 @@ class NumpadInput(object):
self.root.after(0, self.run_action_for_mapped_key, 'x_m', event.x / width) self.root.after(0, self.run_action_for_mapped_key, 'x_m', event.x / width)
self.root.after(0, self.run_action_for_mapped_key, 'y_m', event.y / height) self.root.after(0, self.run_action_for_mapped_key, 'y_m', event.y / height)
#self.run_action_for_mapped_key(event.char) # self.run_action_for_mapped_key(event.char)
def select_display_mode_index(self, index): def select_display_mode_index(self, index):
if index >= len(self.data.get_display_modes_list()): if index >= len(self.data.get_display_modes_list()):
self.message_handler.set_message('ERROR', 'No page %s to display!' % index) self.message_handler.set_message('ERROR', 'No page %s to display!' % index)
else: else:
self.actions.call_method_name("set_display_mode_%s"%self.data.get_display_modes_list()[index]) self.actions.call_method_name("set_display_mode_%s" % self.data.get_display_modes_list()[index])
def run_action_for_mapped_key(self, key, value=-1): def run_action_for_mapped_key(self, key, value=-1):
this_mapping = self.key_mappings[key] this_mapping = self.key_mappings[key]
@@ -101,7 +101,7 @@ class NumpadInput(object):
else: else:
print('the numpad action being called for \'{}\' is {} (mode is {})'.format(key, this_mapping[mode][is_function], mode)) print('the numpad action being called for \'{}\' is {} (mode is {})'.format(key, this_mapping[mode][is_function], mode))
if value != -1: if value != -1:
self.actions.call_method_name(this_mapping[mode][is_function],value) self.actions.call_method_name(this_mapping[mode][is_function], value)
else: else:
self.actions.call_method_name(this_mapping[mode][is_function]) self.actions.call_method_name(this_mapping[mode][is_function])
@@ -111,8 +111,6 @@ class NumpadInput(object):
if not value: if not value:
self.display.refresh_display() self.display.refresh_display()
def check_key_release_settings(self, key): def check_key_release_settings(self, key):
this_mapping = self.key_mappings[key] this_mapping = self.key_mappings[key]
@@ -127,7 +125,7 @@ class NumpadInput(object):
self.run_action_for_mapped_key(key) self.run_action_for_mapped_key(key)
def on_key_disp_release_delay(self): def on_key_disp_release_delay(self):
if not self.in_0_event:# and self.additional_0_in_event==0: if not self.in_0_event: # and self.additional_0_in_event==0:
print("releasing !") print("releasing !")
self.data.is_display_held = False self.data.is_display_held = False
else: else:
@@ -140,36 +138,35 @@ class NumpadInput(object):
else: else:
print("ignoring press!")""" print("ignoring press!")"""
def on_0_key_press(self) : def on_0_key_press(self):
print ("on_0_key_press!") print("on_0_key_press!")
if(not self.in_0_event ): if (not self.in_0_event):
print (" first 0 received!") print(" first 0 received!")
self.in_0_event = True self.in_0_event = True
self.additional_0_in_event = 0 self.additional_0_in_event = 0
self.root.after(self.KEY_000_DELAY, self.check_event_outcome) self.root.after(self.KEY_000_DELAY, self.check_event_outcome)
else: else:
print (" additional 0 received making %s!" % str(self.additional_0_in_event + 1)) print(" additional 0 received making %s!" % str(self.additional_0_in_event + 1))
self.additional_0_in_event = self.additional_0_in_event + 1 self.additional_0_in_event = self.additional_0_in_event + 1
def check_event_outcome(self): def check_event_outcome(self):
if(self.additional_0_in_event == 0 ): if (self.additional_0_in_event == 0):
print (" no additional events, sending s") print(" no additional events, sending s")
self.in_0_event = False self.in_0_event = False
self.run_action_for_mapped_key('s') self.run_action_for_mapped_key('s')
elif(self.additional_0_in_event > 1): elif (self.additional_0_in_event > 1):
print (" %s additional events, sending n"%self.additional_0_in_event) print(" %s additional events, sending n" % self.additional_0_in_event)
self.in_0_event = False self.in_0_event = False
self.run_action_for_mapped_key('n') self.run_action_for_mapped_key('n')
elif(self.additional_0_in_event == 1): elif (self.additional_0_in_event == 1):
print('this doesnt happen - may not be needed') print('this doesnt happen - may not be needed')
self.root.after(self.KEY_000_DELAY, self.second_check_event_outcome) self.root.after(self.KEY_000_DELAY, self.second_check_event_outcome)
def second_check_event_outcome(self): def second_check_event_outcome(self):
print("not supposed to happen?") print("not supposed to happen?")
if(self.additional_0_in_event == 1 ): if (self.additional_0_in_event == 1):
self.in_0_event = False self.in_0_event = False
self.run_action_for_mapped_key('s') self.run_action_for_mapped_key('s')
elif(self.additional_0_in_event > 1): elif (self.additional_0_in_event > 1):
self.in_0_event = False self.in_0_event = False
self.run_action_for_mapped_key('n') self.run_action_for_mapped_key('n')

View File

@@ -45,12 +45,12 @@ class OscInput(object):
this_dispatcher = dispatcher.Dispatcher() this_dispatcher = dispatcher.Dispatcher()
# this_dispatcher.map("/keyboard/*", self.on_osc_input) # this_dispatcher.map("/keyboard/*", self.on_osc_input)
# this_dispatcher.map("/shaderparam0", self.on_param_osc_input) # this_dispatcher.map("/shaderparam0", self.on_param_osc_input)
# this_dispatcher.map("/shaderparam1", self.on_param_osc_input) # this_dispatcher.map("/shaderparam1", self.on_param_osc_input)
# this_dispatcher.map("/shaderparam2", self.on_param_osc_input) # this_dispatcher.map("/shaderparam2", self.on_param_osc_input)
# this_dispatcher.map("/shaderparam3", self.on_param_osc_input) # this_dispatcher.map("/shaderparam3", self.on_param_osc_input)
# this_dispatcher.map("/shutdown", self.exit_osc_server) # this_dispatcher.map("/shutdown", self.exit_osc_server)
this_dispatcher.map("/*", self.on_osc_input) this_dispatcher.map("/*", self.on_osc_input)
try: try:
@@ -63,7 +63,6 @@ class OscInput(object):
except: except:
self.message_handler.set_message('INFO', 'failed to start osc listener') self.message_handler.set_message('INFO', 'failed to start osc listener')
def exit_osc_server(self, unused_addr, args): def exit_osc_server(self, unused_addr, args):
print('%%%%%%%%%%%%%%%%%%%%% exiting external_osc') print('%%%%%%%%%%%%%%%%%%%%% exiting external_osc')
try: try:
@@ -72,15 +71,13 @@ class OscInput(object):
except: except:
self.message_handler.set_message('INFO', 'osc shutdown failed') self.message_handler.set_message('INFO', 'osc shutdown failed')
def on_osc_input(self, addr, args): def on_osc_input(self, addr, args):
if 'keyboard' in addr: if 'keyboard' in addr:
self.on_key_osc_input(addr, args) self.on_key_osc_input(addr, args)
elif 'shutdown' in addr: elif 'shutdown' in addr:
self.exit_osc_server(addr, args) self.exit_osc_server(addr, args)
else: else:
self.on_param_osc_input(addr,args) self.on_param_osc_input(addr, args)
def on_key_osc_input(self, addr, args): def on_key_osc_input(self, addr, args):
args = str(args) args = str(args)
@@ -123,4 +120,3 @@ class OscInput(object):
if 'continuous' not in method_name: if 'continuous' not in method_name:
self.display.refresh_display() self.display.refresh_display()

View File

@@ -1,23 +1,20 @@
def generate_mappings_doc(title, mappings, column_one_header="Note/CC"): def generate_mappings_doc(title, mappings, column_one_header="Note/CC"):
#print(mappings) # print(mappings)
output = "" output = ""
output += "# %s\n" % title output += "# %s\n" % title
output += "\n| %s | Mode | Action (default) | Action (with FN) | \n" % column_one_header output += "\n| %s | Mode | Action (default) | Action (with FN) | \n" % column_one_header
output += ("| --- " * 4) + " |\n" output += ("| --- " * 4) + " |\n"
for message, maps in sorted(mappings.items()): for message, maps in sorted(mappings.items()):
#output += "| %s | " % message # output += "| %s | " % message
for mode, actions in sorted(maps.items()): for mode, actions in sorted(maps.items()):
output += "| " output += "| "
output += "%s\t| " % message output += "%s\t| " % message
output += "%s\t| " % mode output += "%s\t| " % mode
output += "%s | " % actions[0] output += "%s | " % actions[0]
if len(actions)>1: if len(actions) > 1:
output += "%s | " % actions[1] output += "%s | " % actions[1]
output += "|\n" output += "|\n"
output += "\n----\n" output += "\n----\n"
print(output) print(output)

View File

@@ -1,5 +1,3 @@
class AltVideoPlayer: class AltVideoPlayer:
def __init__(self, root, message_handler, data, osc_client, name): def __init__(self, root, message_handler, data, osc_client, name):
self.root = root self.root = root
@@ -18,15 +16,14 @@ class AltVideoPlayer:
self.load_attempts = 0 self.load_attempts = 0
self.alpha = 0 self.alpha = 0
self.show_toggle_on = True self.show_toggle_on = True
### new stuff ### new stuff
self.client = osc_client self.client = osc_client
self.position = -1 self.position = -1
def try_load(self, layer, is_current=False): def try_load(self, layer, is_current=False):
load_attempts = 0 load_attempts = 0
while(load_attempts < 2): while (load_attempts < 2):
load_attempts = load_attempts + 1 load_attempts = load_attempts + 1
if self.load(layer, is_current): if self.load(layer, is_current):
print('load success') print('load success')
@@ -37,7 +34,6 @@ class AltVideoPlayer:
self.status = 'ERROR' self.status = 'ERROR'
return False return False
def load(self, layer, is_current=False): def load(self, layer, is_current=False):
self.get_context_for_player(is_current) self.get_context_for_player(is_current)
print('the location is {}'.format(self.location)) print('the location is {}'.format(self.location))
@@ -45,9 +41,9 @@ class AltVideoPlayer:
self.status = 'EMPTY' self.status = 'EMPTY'
return True return True
if(self.end is -1): if (self.end is -1):
self.end = self.total_length self.end = self.total_length
if(self.start is -1): if (self.start is -1):
self.start = 0 self.start = 0
self.client.send_message("/player/{}/load".format(self.name[0]), [self.location, self.start / self.total_length, self.end / self.total_length, self.rate]) self.client.send_message("/player/{}/load".format(self.name[0]), [self.location, self.start / self.total_length, self.end / self.total_length, self.rate])
self.crop_length = self.end - self.start self.crop_length = self.end - self.start
@@ -57,10 +53,10 @@ class AltVideoPlayer:
pass pass
self.set_alpha_value(0) self.set_alpha_value(0)
return True return True
#except (ValueError, SystemError) as e: # except (ValueError, SystemError) as e:
# print(e) # print(e)
#self.message_handler.set_message('ERROR', 'load attempt fail') # self.message_handler.set_message('ERROR', 'load attempt fail')
#return False # return False
def start_video(self): def start_video(self):
if 'play' in self.data.settings['sampler']['ON_START']['value']: if 'play' in self.data.settings['sampler']['ON_START']['value']:
@@ -73,9 +69,6 @@ class AltVideoPlayer:
else: else:
self.set_alpha_value(0) self.set_alpha_value(0)
def reload(self, layer, is_current=False): def reload(self, layer, is_current=False):
self.exit() self.exit()
self.player_running = False self.player_running = False
@@ -149,14 +142,13 @@ class AltVideoPlayer:
self.root.after(100, self.exit) self.root.after(100, self.exit)
def exit(self): def exit(self):
#self.last_player.exit() # self.last_player.exit()
try: try:
self.client.send_message("/player/{}/quit".format(self.name[0]),True) self.client.send_message("/player/{}/quit".format(self.name[0]), True)
self.player_running = False self.player_running = False
except: except:
pass pass
## not sure if i am going to implement this atm ## not sure if i am going to implement this atm
def set_screen_size_for_dev_mode(self): def set_screen_size_for_dev_mode(self):
if self.data.settings['system']['DEV_MODE_RESET']['value'] == 'on': if self.data.settings['system']['DEV_MODE_RESET']['value'] == 'on':
@@ -165,17 +157,3 @@ class AltVideoPlayer:
else: else:
aspect_mode = self.data.settings['video']['SCREEN_MODE']['value'] aspect_mode = self.data.settings['video']['SCREEN_MODE']['value']
return False, '--aspect-mode', aspect_mode return False, '--aspect-mode', aspect_mode

View File

@@ -23,7 +23,6 @@ class Capture(object):
## some capture settings ## some capture settings
def create_capture_device(self): def create_capture_device(self):
if self.data.settings['capture']['TYPE']['value'] != 'usb': if self.data.settings['capture']['TYPE']['value'] != 'usb':
if self.use_capture: if self.use_capture:
@@ -32,7 +31,7 @@ class Capture(object):
self.update_capture_settings() self.update_capture_settings()
try: try:
self.device = picamera.PiCamera(resolution=self.resolution, framerate=self.framerate, sensor_mode = self.sensor_mode) self.device = picamera.PiCamera(resolution=self.resolution, framerate=self.framerate, sensor_mode=self.sensor_mode)
return True return True
except picamera.exc.PiCameraError as e: except picamera.exc.PiCameraError as e:
self.use_capture = False self.use_capture = False
@@ -70,7 +69,6 @@ class Capture(object):
self.device.framerate = self.framerate self.device.framerate = self.framerate
self.device.resolution = self.resolution self.device.resolution = self.resolution
def start_preview(self): def start_preview(self):
if self.use_capture == False: if self.use_capture == False:
self.message_handler.set_message('INFO', 'capture not enabled') self.message_handler.set_message('INFO', 'capture not enabled')
@@ -96,7 +94,6 @@ class Capture(object):
else: else:
self.sensor_mode = 0 self.sensor_mode = 0
def set_preview_screen_size(self): def set_preview_screen_size(self):
if self.data.settings['system']['DEV_MODE_RESET']['value'] == 'on': if self.data.settings['system']['DEV_MODE_RESET']['value'] == 'on':
self.device.preview.fullscreen = False self.device.preview.fullscreen = False
@@ -145,7 +142,7 @@ class Capture(object):
def stop_recording(self): def stop_recording(self):
self.device.stop_recording() self.device.stop_recording()
#set status to saving # set status to saving
mp4box_process, recording_name = self.convert_raw_recording() mp4box_process, recording_name = self.convert_raw_recording()
self.is_recording = 'saving' self.is_recording = 'saving'
self.root.after(0, self.wait_for_recording_to_save, mp4box_process, recording_name) self.root.after(0, self.wait_for_recording_to_save, mp4box_process, recording_name)
@@ -156,22 +153,21 @@ class Capture(object):
self.device.close() self.device.close()
def convert_raw_recording(self): def convert_raw_recording(self):
recording_path , recording_name = self.generate_recording_path() recording_path, recording_name = self.generate_recording_path()
try: try:
if self.sensor_mode == 6: if self.sensor_mode == 6:
mp4box_process = subprocess.Popen(['MP4Box', '-fps', '60', '-add', self.video_dir + '/raw.h264', recording_path]) mp4box_process = subprocess.Popen(['MP4Box', '-fps', '60', '-add', self.video_dir + '/raw.h264', recording_path])
return mp4box_process , recording_name return mp4box_process, recording_name
else: else:
mp4box_process = subprocess.Popen(['MP4Box', '-add', self.video_dir + '/raw.h264', recording_path]) mp4box_process = subprocess.Popen(['MP4Box', '-add', self.video_dir + '/raw.h264', recording_path])
return mp4box_process , recording_name return mp4box_process, recording_name
except Exception as e: except Exception as e:
print(e) print(e)
if hasattr(e, 'message'): if hasattr(e, 'message'):
error_info = e.message error_info = e.message
else: else:
error_info = e error_info = e
self.message_handler.set_message('ERROR',error_info) self.message_handler.set_message('ERROR', error_info)
def wait_for_recording_to_save(self, process, name): def wait_for_recording_to_save(self, process, name):
print('the poll is {}'.format(process.poll())) print('the poll is {}'.format(process.poll()))
@@ -188,10 +184,10 @@ class Capture(object):
os.makedirs(rec_dir) os.makedirs(rec_dir)
date = datetime.datetime.now().strftime("%Y-%m-%d") date = datetime.datetime.now().strftime("%Y-%m-%d")
i = 0 i = 0
while os.path.exists('{}/rec-{}-{}.mp4'.format(rec_dir,date, i)): while os.path.exists('{}/rec-{}-{}.mp4'.format(rec_dir, date, i)):
i += 1 i += 1
name = 'rec-{}-{}.mp4'.format(date, i) name = 'rec-{}-{}.mp4'.format(date, i)
return '{}/{}'.format(rec_dir,name), name return '{}/{}'.format(rec_dir, name), name
def get_recording_time(self): def get_recording_time(self):
if not self.device or not self.device.recording or self.device.frame.timestamp == None: if not self.device or not self.device.recording or self.device.frame.timestamp == None:
@@ -209,7 +205,7 @@ class Capture(object):
error_info = e.message error_info = e.message
else: else:
error_info = e error_info = e
self.message_handler.set_message('ERROR',error_info) self.message_handler.set_message('ERROR', error_info)
return 0 return 0
return 0 return 0
@@ -255,4 +251,3 @@ class Capture(object):
def receive_recording_finished(self, path, value): def receive_recording_finished(self, path, value):
pass pass

View File

@@ -21,7 +21,7 @@ class OfCapture(object):
self.recording_start_time = 0 self.recording_start_time = 0
self.update_capture_settings() self.update_capture_settings()
self.of_recording_finished = True self.of_recording_finished = True
#self.create_capture_device() # self.create_capture_device()
def create_capture_device(self): def create_capture_device(self):
if self.use_capture and self.capture_type != 'usb': if self.use_capture and self.capture_type != 'usb':
@@ -37,7 +37,6 @@ class OfCapture(object):
self.has_capture = True self.has_capture = True
return True return True
def piCapture_with_no_source(self): def piCapture_with_no_source(self):
is_piCapture = subprocess.check_output(['pivideo', '--query', 'ready']) is_piCapture = subprocess.check_output(['pivideo', '--query', 'ready'])
if 'Video Processor was not found' not in str(is_piCapture): if 'Video Processor was not found' not in str(is_piCapture):
@@ -62,7 +61,7 @@ class OfCapture(object):
def check_if_attached_with_picamera(self): def check_if_attached_with_picamera(self):
print('about to try open pcamera to check..') print('about to try open pcamera to check..')
try: try:
device = picamera.PiCamera(resolution=self.resolution, framerate=self.framerate, sensor_mode = self.sensor_mode) device = picamera.PiCamera(resolution=self.resolution, framerate=self.framerate, sensor_mode=self.sensor_mode)
device.close() device.close()
return True return True
except picamera.exc.PiCameraError as e: except picamera.exc.PiCameraError as e:
@@ -109,7 +108,7 @@ class OfCapture(object):
self.is_recording = True self.is_recording = True
self.of_recording_finished = False self.of_recording_finished = False
self.recording_start_time = time.time() self.recording_start_time = time.time()
#self.device.start_recording(self.video_dir + '/raw.h264') # self.device.start_recording(self.video_dir + '/raw.h264')
self.osc_client.send_message("/capture/record/start", True) self.osc_client.send_message("/capture/record/start", True)
self.monitor_disk_space() self.monitor_disk_space()
@@ -129,12 +128,11 @@ class OfCapture(object):
return True return True
def stop_recording(self): def stop_recording(self):
#self.device.stop_recording() # self.device.stop_recording()
self.osc_client.send_message("/capture/record/stop", True) self.osc_client.send_message("/capture/record/stop", True)
self.is_recording = 'saving' self.is_recording = 'saving'
self.wait_for_raw_file() self.wait_for_raw_file()
#set status to saving # set status to saving
def wait_for_raw_file(self): def wait_for_raw_file(self):
if os.path.exists(self.video_dir + 'raw.h264'): if os.path.exists(self.video_dir + 'raw.h264'):
@@ -143,8 +141,8 @@ class OfCapture(object):
self.root.after(0, self.wait_for_recording_to_save, mp4box_process, recording_name) self.root.after(0, self.wait_for_recording_to_save, mp4box_process, recording_name)
self.update_capture_settings() self.update_capture_settings()
elif os.path.exists(self.video_dir + 'raw.mp4') and self.of_recording_finished: elif os.path.exists(self.video_dir + 'raw.mp4') and self.of_recording_finished:
recording_path , recording_name = self.generate_recording_path() recording_path, recording_name = self.generate_recording_path()
os.rename(self.video_dir + 'raw.mp4', recording_path ) os.rename(self.video_dir + 'raw.mp4', recording_path)
self.is_recording = False self.is_recording = False
self.data.create_new_slot_mapping_in_first_open(recording_name) self.data.create_new_slot_mapping_in_first_open(recording_name)
self.update_capture_settings() self.update_capture_settings()
@@ -154,21 +152,20 @@ class OfCapture(object):
def convert_raw_recording(self): def convert_raw_recording(self):
### wait for omx to finish creating video ... ### wait for omx to finish creating video ...
if os.path.exists(self.video_dir + 'raw.h264'): if os.path.exists(self.video_dir + 'raw.h264'):
recording_path , recording_name = self.generate_recording_path() recording_path, recording_name = self.generate_recording_path()
framerate = 30 # hardcoded in openframeworks code for now framerate = 30 # hardcoded in openframeworks code for now
if self.capture_type == "piCaptureSd1": if self.capture_type == "piCaptureSd1":
framerate = framerate*2 # because picapture is interlaced framerate = framerate * 2 # because picapture is interlaced
try: try:
mp4box_process = subprocess.Popen(['MP4Box', '-add', self.video_dir + 'raw.h264:fps={}'.format(framerate), recording_path]) mp4box_process = subprocess.Popen(['MP4Box', '-add', self.video_dir + 'raw.h264:fps={}'.format(framerate), recording_path])
return mp4box_process , recording_name return mp4box_process, recording_name
except Exception as e: except Exception as e:
print(e) print(e)
if hasattr(e, 'message'): if hasattr(e, 'message'):
error_info = e.message error_info = e.message
else: else:
error_info = e error_info = e
self.message_handler.set_message('ERROR',error_info) self.message_handler.set_message('ERROR', error_info)
def wait_for_recording_to_save(self, process, name): def wait_for_recording_to_save(self, process, name):
print('the poll is {}'.format(process.poll())) print('the poll is {}'.format(process.poll()))
@@ -185,10 +182,10 @@ class OfCapture(object):
os.makedirs(rec_dir) os.makedirs(rec_dir)
date = datetime.datetime.now().strftime("%Y-%m-%d") date = datetime.datetime.now().strftime("%Y-%m-%d")
i = 0 i = 0
while os.path.exists('{}/rec-{}-{}.mp4'.format(rec_dir,date, i)): while os.path.exists('{}/rec-{}-{}.mp4'.format(rec_dir, date, i)):
i += 1 i += 1
name = 'rec-{}-{}.mp4'.format(date, i) name = 'rec-{}-{}.mp4'.format(date, i)
return '{}/{}'.format(rec_dir,name), name return '{}/{}'.format(rec_dir, name), name
def receive_recording_finished(self, unused_addr, position): def receive_recording_finished(self, unused_addr, position):
print('recieved recording finshed message !!!!') print('recieved recording finshed message !!!!')
@@ -196,9 +193,9 @@ class OfCapture(object):
def get_recording_time(self): def get_recording_time(self):
return time.time() - self.recording_start_time return time.time() - self.recording_start_time
#if not self.device or not self.device.recording or self.device.frame.timestamp == None: # if not self.device or not self.device.recording or self.device.frame.timestamp == None:
# return -1 # return -1
#else: # else:
# return self.device.frame.timestamp / 1000000 # return self.device.frame.timestamp / 1000000
def get_preview_alpha(self): def get_preview_alpha(self):
@@ -226,6 +223,3 @@ class OfCapture(object):
return int(1000000 / self.framerate) return int(1000000 / self.framerate)
else: else:
return int(fractions.Fraction(setting_value) * 1000000) return int(fractions.Fraction(setting_value) * 1000000)

View File

@@ -7,7 +7,7 @@ from data_centre.plugin_collection import ModulationReceiverPlugin
class Shaders(object): class Shaders(object):
MENU_HEIGHT = 10 MENU_HEIGHT = 10
EMPTY_SHADER = dict(name='none',is_shader=True,shad_type='-',param_number=4,path='-') EMPTY_SHADER = dict(name='none', is_shader=True, shad_type='-', param_number=4, path='-')
MAX_MOD_SLOTS = 4 MAX_MOD_SLOTS = 4
@@ -17,27 +17,27 @@ class Shaders(object):
self.message_handler = message_handler self.message_handler = message_handler
self.message_handler.shaders = self self.message_handler.shaders = self
self.data = data self.data = data
self.shaders_menu = menu.ShadersMenu(self.data, self.message_handler, self.MENU_HEIGHT ) self.shaders_menu = menu.ShadersMenu(self.data, self.message_handler, self.MENU_HEIGHT)
self.selected_shader_list = [self.EMPTY_SHADER for i in range(3)] self.selected_shader_list = [self.EMPTY_SHADER for i in range(3)]
self.focused_param = 0 self.focused_param = 0
self.shaders_menu_list = self.generate_shaders_list() self.shaders_menu_list = self.generate_shaders_list()
self.selected_modulation_slot = 0 self.selected_modulation_slot = 0
self.selected_status_list = ['-','-','-'] ## going to try using symbols for this : '-' means empty, '▶' means running, '■' means not running, '!' means error self.selected_status_list = ['-', '-', '-'] ## going to try using symbols for this : '-' means empty, '▶' means running, '■' means not running, '!' means error
self.selected_param_list = [[0.0,0.0,0.0,0.0] for i in range(3)] self.selected_param_list = [[0.0, 0.0, 0.0, 0.0] for i in range(3)]
self.selected_speed_list = [1.0, 1.0, 1.0] self.selected_speed_list = [1.0, 1.0, 1.0]
self.selected_modulation_slot = 0 self.selected_modulation_slot = 0
#self.modulation_level = [[[0.0,0.0,0.0,0.0] for i in range(4)] for i in range(3)] # self.modulation_level = [[[0.0,0.0,0.0,0.0] for i in range(4)] for i in range(3)]
self.modulation_value = [0.0] * self.MAX_MOD_SLOTS #,0.0,0.0,0.0] self.modulation_value = [0.0] * self.MAX_MOD_SLOTS # ,0.0,0.0,0.0]
#self.load_selected_shader() # self.load_selected_shader()
@property @property
def modulation_level(self): def modulation_level(self):
return self.data.settings['shader'].setdefault('modulation_level', return self.data.settings['shader'].setdefault('modulation_level',
[[[0.0,0.0,0.0,0.0] for i in range(4)] for i in range(3)]) [[[0.0, 0.0, 0.0, 0.0] for i in range(4)] for i in range(3)])
def set_modulation_levels(self, levels): def set_modulation_levels(self, levels):
self.data.settings['shader']['modulation_level'] = levels self.data.settings['shader']['modulation_level'] = levels
@@ -52,13 +52,12 @@ class Shaders(object):
shad_type = self.determine_shader_type(path) shad_type = self.determine_shader_type(path)
parameter_number = self.determine_shader_parameter_number(path) parameter_number = self.determine_shader_parameter_number(path)
shaders_menu_list.append(dict(name=line['name'],is_shader=True,shad_type=shad_type,param_number=parameter_number,path=path)) shaders_menu_list.append(dict(name=line['name'], is_shader=True, shad_type=shad_type, param_number=parameter_number, path=path))
else: else:
shaders_menu_list.append(dict(name=line['name'],is_shader=False,shad_type='',param_number=None,path=None)) shaders_menu_list.append(dict(name=line['name'], is_shader=False, shad_type='', param_number=None, path=None))
return shaders_menu_list return shaders_menu_list
def get_path_for_shader(self, file_name): def get_path_for_shader(self, file_name):
######## returns full path for a given file name ######## ######## returns full path for a given file name ########
for path in self.data.PATHS_TO_SHADERS: for path in self.data.PATHS_TO_SHADERS:
@@ -79,7 +78,6 @@ class Shaders(object):
else: else:
return '-' return '-'
def determine_shader_parameter_number(self, path): def determine_shader_parameter_number(self, path):
max_amount = 4 max_amount = 4
if True: # for now always assume 4 params if True: # for now always assume 4 params
@@ -93,9 +91,9 @@ class Shaders(object):
def load_shader_layer(self, layer): def load_shader_layer(self, layer):
selected_shader = self.selected_shader_list[layer] selected_shader = self.selected_shader_list[layer]
#self.selected_param_list[self.data.shader_layer] = [0.0,0.0,0.0,0.0] # self.selected_param_list[self.data.shader_layer] = [0.0,0.0,0.0,0.0]
print("select shader: ", selected_shader) print("select shader: ", selected_shader)
self.osc_client.send_message("/shader/{}/load".format(str(layer)), [selected_shader['path'],selected_shader['shad_type'] == '2in',selected_shader['param_number']]) self.osc_client.send_message("/shader/{}/load".format(str(layer)), [selected_shader['path'], selected_shader['shad_type'] == '2in', selected_shader['param_number']])
if not self.selected_status_list[layer] == '': if not self.selected_status_list[layer] == '':
self.selected_status_list[layer] = '' self.selected_status_list[layer] = ''
@@ -152,7 +150,7 @@ class Shaders(object):
self.selected_shader_list[layer]['slot'] = slot self.selected_shader_list[layer]['slot'] = slot
self.load_shader_layer(layer) self.load_shader_layer(layer)
else: else:
self.message_handler.set_message('INFO', "shader slot %s:%s is empty"%(layer,slot)) self.message_handler.set_message('INFO', "shader slot %s:%s is empty" % (layer, slot))
def play_this_shader(self, slot): def play_this_shader(self, slot):
print(self.data.shader_bank_data[self.data.shader_layer]) print(self.data.shader_bank_data[self.data.shader_layer])
@@ -161,13 +159,13 @@ class Shaders(object):
def increase_this_param(self, amount_change): def increase_this_param(self, amount_change):
param = self.focused_param param = self.focused_param
current_amount = self.selected_param_list[self.data.shader_layer][param] current_amount = self.selected_param_list[self.data.shader_layer][param]
amount = self.get_new_param_amount(current_amount,amount_change) amount = self.get_new_param_amount(current_amount, amount_change)
self.set_param_to_amount(param, amount) self.set_param_to_amount(param, amount)
def decrease_this_param(self, amount_change): def decrease_this_param(self, amount_change):
param = self.focused_param param = self.focused_param
current_amount = self.selected_param_list[self.data.shader_layer][param] current_amount = self.selected_param_list[self.data.shader_layer][param]
amount = self.get_new_param_amount(current_amount,-amount_change) amount = self.get_new_param_amount(current_amount, -amount_change)
self.set_param_to_amount(param, amount) self.set_param_to_amount(param, amount)
def toggle_shader_speed(self): def toggle_shader_speed(self):
@@ -190,11 +188,11 @@ class Shaders(object):
def select_previous_shader_modulation_slot(self): def select_previous_shader_modulation_slot(self):
self.selected_modulation_slot -= 1 self.selected_modulation_slot -= 1
if self.selected_modulation_slot < 0: if self.selected_modulation_slot < 0:
self.selected_modulation_slot = self.MAX_MOD_SLOTS-1 self.selected_modulation_slot = self.MAX_MOD_SLOTS - 1
def reset_modulation(self, slot): def reset_modulation(self, slot):
for layer in self.modulation_level: for layer in self.modulation_level:
for layer,levels in enumerate(layer): for layer, levels in enumerate(layer):
levels[slot] = 0.0 levels[slot] = 0.0
def reset_selected_modulation(self): def reset_selected_modulation(self):
@@ -222,44 +220,46 @@ class Shaders(object):
def set_param_layer_to_amount(self, param, layer, amount): def set_param_layer_to_amount(self, param, layer, amount):
if self.data.settings['shader']['X3_AS_SPEED']['value'] == 'enabled' and param == 3: if self.data.settings['shader']['X3_AS_SPEED']['value'] == 'enabled' and param == 3:
self.set_speed_layer_to_amount(layer, amount) #layer_offset=layer-self.data.shader_layer) self.set_speed_layer_to_amount(layer, amount) # layer_offset=layer-self.data.shader_layer)
else: else:
self.selected_param_list[layer][param] = amount self.selected_param_list[layer][param] = amount
self.update_param_layer(param,layer) self.update_param_layer(param, layer)
def get_modulation_value_list(self, amount, values, levels): def get_modulation_value_list(self, amount, values, levels):
l = [] l = []
for i,v in enumerate(values): for i, v in enumerate(values):
l.append(self.get_modulation_value(amount, v, levels[i])) l.append(self.get_modulation_value(amount, v, levels[i]))
#print ("got mean %s from amount %s with %s*%s" % (mean(l), amount, values, levels)) # print ("got mean %s from amount %s with %s*%s" % (mean(l), amount, values, levels))
return mean(l) return mean(l)
def get_modulation_value(self, amount, value, level): def get_modulation_value(self, amount, value, level):
if level==0: if level == 0:
return amount return amount
# TODO: read from list of input formulas, from plugins etc to modulate the value # TODO: read from list of input formulas, from plugins etc to modulate the value
temp_amount = amount + (value * level) temp_amount = amount + (value * level)
#print("from amount %s, modulation is %s, temp_amount is %s" % (amount, modulation, temp_amount)) # 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 < 0:
if temp_amount > 1: temp_amount = 1 # modulation however is -1 to +1 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 return temp_amount
def send_param_layer_amount_message(self, param, layer, amount): def send_param_layer_amount_message(self, param, layer, amount):
self.osc_client.send_message("/shader/{}/param".format(str(layer)), [param, amount] ) self.osc_client.send_message("/shader/{}/param".format(str(layer)), [param, amount])
def modulate_param_to_amount(self, param, value): def modulate_param_to_amount(self, param, value):
# incoming data here should be in format 0 to 1; needs changing to -1 to +1 # incoming data here should be in format 0 to 1; needs changing to -1 to +1
self.modulation_value[param] = (value-0.5)*2 # normalise to -1 to +1 self.modulation_value[param] = (value - 0.5) * 2 # normalise to -1 to +1
for plugin in self.data.plugins.get_plugins(ModulationReceiverPlugin): for plugin in self.data.plugins.get_plugins(ModulationReceiverPlugin):
plugin.set_modulation_value(param, self.modulation_value[param]) plugin.set_modulation_value(param, self.modulation_value[param])
for layer,params in enumerate(self.selected_param_list): for layer, params in enumerate(self.selected_param_list):
for ip,p in enumerate(params): for ip, p in enumerate(params):
for p2,v in enumerate(self.modulation_level[layer][ip]): for p2, v in enumerate(self.modulation_level[layer][ip]):
if v!=0: if v != 0:
self.update_param_layer(ip,layer) self.update_param_layer(ip, layer)
break break
def set_param_layer_offset_modulation_level(self, param, layer, level): def set_param_layer_offset_modulation_level(self, param, layer, level):
@@ -279,7 +279,7 @@ class Shaders(object):
self.send_param_layer_amount_message(param, layer, self.send_param_layer_amount_message(param, layer,
self.get_modulation_value_list( self.get_modulation_value_list(
self.selected_param_list[layer][param], self.selected_param_list[layer][param],
self.modulation_value,#[0], #param], self.modulation_value, # [0], #param],
self.modulation_level[layer][param] self.modulation_level[layer][param]
) )
) )
@@ -292,6 +292,5 @@ class Shaders(object):
self.set_speed_layer_to_amount(layer, amount) self.set_speed_layer_to_amount(layer, amount)
def set_speed_layer_to_amount(self, layer, amount): def set_speed_layer_to_amount(self, layer, amount):
self.osc_client.send_message("/shader/{}/speed".format(str(layer)), amount ) self.osc_client.send_message("/shader/{}/speed".format(str(layer)), amount)
self.selected_speed_list[layer] = amount self.selected_speed_list[layer] = amount

View File

@@ -3,7 +3,6 @@ from video_centre.video_player import VideoPlayer
class VideoDriver(object): class VideoDriver(object):
MAX_LAYER = 254 MAX_LAYER = 254
def __init__(self, root, osc_client, message_handler, data): def __init__(self, root, osc_client, message_handler, data):
@@ -30,9 +29,7 @@ class VideoDriver(object):
self.root.after(self.delay, self.begin_playing_parallel) self.root.after(self.delay, self.begin_playing_parallel)
else: else:
self.root.after(self.delay, self.begin_playing) self.root.after(self.delay, self.begin_playing)
#self.print_status() # self.print_status()
def update_video_settings(self): def update_video_settings(self):
self.switch_on_finish = self.data.settings['sampler']['ON_FINISH']['value'] == 'switch' self.switch_on_finish = self.data.settings['sampler']['ON_FINISH']['value'] == 'switch'
@@ -49,8 +46,8 @@ class VideoDriver(object):
def print_status(self): def print_status(self):
print('self.loop_parallel: ', self.loop_parallel, 'self.in_parallel_cycle :', self.in_parallel_cycle) print('self.loop_parallel: ', self.loop_parallel, 'self.in_parallel_cycle :', self.in_parallel_cycle)
print('l({}):{}, c({}):{}, n({}):{}'.format(self.last_player.name, self.last_player.status, self.current_player.name, \ print('l({}):{}, c({}):{}, n({}):{}'.format(self.last_player.name, self.last_player.status, self.current_player.name, \
self.current_player.status, self.next_player.name, self.next_player.status,)) self.current_player.status, self.next_player.name, self.next_player.status, ))
self.root.after(1000,self.print_status) self.root.after(1000, self.print_status)
def begin_playing(self): def begin_playing(self):
if self.current_player.try_load(self.get_next_layer_value()): if self.current_player.try_load(self.get_next_layer_value()):
@@ -115,7 +112,6 @@ class VideoDriver(object):
else: else:
self.in_next_load_cycle = False self.in_next_load_cycle = False
def get_player_info_for_status(self): def get_player_info_for_status(self):
return self.current_player.bankslot_number, self.current_player.status, self.current_player.alpha, \ 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 self.next_player.bankslot_number, self.next_player.status, self.next_player.alpha
@@ -131,19 +127,19 @@ class VideoDriver(object):
self.next_player.exit() self.next_player.exit()
if self.current_player: if self.current_player:
self.current_player.exit() self.current_player.exit()
if self. last_player: if self.last_player:
self.last_player.exit() self.last_player.exit()
def reset_all_players(self): def reset_all_players(self):
self.exit_all_players() self.exit_all_players()
state = self.data.settings['video']['VIDEOPLAYER_BACKEND']['value'] state = self.data.settings['video']['VIDEOPLAYER_BACKEND']['value']
if(state == 'ofvideoplayer' or state == 'ofxomxplayer'): if (state == 'ofvideoplayer' or state == 'ofxomxplayer'):
self.last_player = AltVideoPlayer(self.root, self.message_handler, self.data, self.osc_client, 'a.a') self.last_player = AltVideoPlayer(self.root, self.message_handler, self.data, self.osc_client, 'a.a')
self.current_player = AltVideoPlayer(self.root,self.message_handler, self.data, self.osc_client, 'b.b') self.current_player = AltVideoPlayer(self.root, self.message_handler, self.data, self.osc_client, 'b.b')
self.next_player = AltVideoPlayer(self.root, self.message_handler, self.data, self.osc_client, 'c.c') self.next_player = AltVideoPlayer(self.root, self.message_handler, self.data, self.osc_client, 'c.c')
else: else:
self.last_player = VideoPlayer(self.root, self.message_handler, self.data, 'a.a') self.last_player = VideoPlayer(self.root, self.message_handler, self.data, 'a.a')
self.current_player = VideoPlayer(self.root,self.message_handler, self.data, 'b.b') self.current_player = VideoPlayer(self.root, self.message_handler, self.data, 'b.b')
self.next_player = VideoPlayer(self.root, self.message_handler, self.data, 'c.c') self.next_player = VideoPlayer(self.root, self.message_handler, self.data, 'c.c')
def reload_next_player(self): def reload_next_player(self):
@@ -154,7 +150,7 @@ class VideoDriver(object):
def receive_position(self, unused_addr, player_name, args): def receive_position(self, unused_addr, player_name, args):
for player in [self.next_player, self.current_player, self.last_player]: for player in [self.next_player, self.current_player, self.last_player]:
if player_name[0] in player.name : if player_name[0] in player.name:
player.position = args * player.total_length player.position = args * player.total_length
break break

View File

@@ -1,5 +1,6 @@
from omxplayer.player import OMXPlayer from omxplayer.player import OMXPlayer
class VideoPlayer: class VideoPlayer:
def __init__(self, root, message_handler, data, name): def __init__(self, root, message_handler, data, name):
self.root = root self.root = root
@@ -20,10 +21,9 @@ class VideoPlayer:
self.alpha = 0 self.alpha = 0
self.show_toggle_on = False self.show_toggle_on = False
def try_load(self, layer, is_current=False): def try_load(self, layer, is_current=False):
load_attempts = 0 load_attempts = 0
while(load_attempts < 2): while (load_attempts < 2):
load_attempts = load_attempts + 1 load_attempts = load_attempts + 1
if self.load(layer, is_current): if self.load(layer, is_current):
print('load success') print('load success')
@@ -34,9 +34,8 @@ class VideoPlayer:
self.status = 'ERROR' self.status = 'ERROR'
return False return False
def load(self, layer, is_current=False): def load(self, layer, is_current=False):
#try: # try:
self.get_context_for_player(is_current) self.get_context_for_player(is_current)
is_dev_mode, first_screen_arg, second_screen_arg = self.set_screen_size_for_dev_mode() is_dev_mode, first_screen_arg, second_screen_arg = self.set_screen_size_for_dev_mode()
arguments = ['--no-osd', '--layer', str(layer), '--adev', 'local', '--alpha', '0', first_screen_arg, second_screen_arg] arguments = ['--no-osd', '--layer', str(layer), '--adev', 'local', '--alpha', '0', first_screen_arg, second_screen_arg]
@@ -50,9 +49,9 @@ class VideoPlayer:
self.omx_player = OMXPlayer(self.location, args=arguments, dbus_name=self.name) self.omx_player = OMXPlayer(self.location, args=arguments, dbus_name=self.name)
self.omx_running = True self.omx_running = True
self.total_length = self.omx_player.duration() # <-- uneeded once self.duration stores float self.total_length = self.omx_player.duration() # <-- uneeded once self.duration stores float
if(self.end is -1): if (self.end is -1):
self.end = self.total_length self.end = self.total_length
if(self.start is -1): if (self.start is -1):
self.start = 0 self.start = 0
self.crop_length = self.end - self.start self.crop_length = self.end - self.start
print('{}: the duration is {}'.format(self.name, self.total_length)) print('{}: the duration is {}'.format(self.name, self.total_length))
@@ -64,14 +63,14 @@ class VideoPlayer:
self.set_alpha_value(0) self.set_alpha_value(0)
self.pause_at_start() self.pause_at_start()
return True return True
#except (ValueError, SystemError) as e: # except (ValueError, SystemError) as e:
# print(e) # print(e)
#self.message_handler.set_message('ERROR', 'load attempt fail') # self.message_handler.set_message('ERROR', 'load attempt fail')
#return False # return False
def pause_at_start(self): def pause_at_start(self):
position = self.get_position() position = self.get_position()
start_threshold = round(self.start - 0.02,2) start_threshold = round(self.start - 0.02, 2)
if position > start_threshold: if position > start_threshold:
if self.status == 'LOADING': if self.status == 'LOADING':
self.status = 'LOADED' self.status = 'LOADED'
@@ -94,12 +93,12 @@ class VideoPlayer:
def pause_at_end(self): def pause_at_end(self):
position = self.get_position() position = self.get_position()
end_threshold = self.end - 0.2 end_threshold = self.end - 0.2
if(position > end_threshold): if (position > end_threshold):
self.status = 'FINISHED' self.status = 'FINISHED'
self.omx_player.pause() self.omx_player.pause()
print('its paused at end!') print('its paused at end!')
elif(self.omx_running): elif (self.omx_running):
self.root.after(5, self.pause_at_end) self.root.after(5, self.pause_at_end)
def reload(self, layer, is_current=False): def reload(self, layer, is_current=False):
@@ -123,7 +122,7 @@ class VideoPlayer:
def get_context_for_player(self, is_current=False): def get_context_for_player(self, is_current=False):
next_context = self.data.get_next_context(is_current) next_context = self.data.get_next_context(is_current)
self.location = next_context['location'] self.location = next_context['location']
#self.total_length = next_context['length'] # self.total_length = next_context['length']
self.start = next_context['start'] self.start = next_context['start']
self.end = next_context['end'] self.end = next_context['end']
self.bankslot_number = next_context['bankslot_number'] self.bankslot_number = next_context['bankslot_number']
@@ -152,7 +151,7 @@ class VideoPlayer:
after_seek_position = position + amount after_seek_position = position + amount
if after_seek_position > self.start and after_seek_position < self.end: if after_seek_position > self.start and after_seek_position < self.end:
self.set_position(after_seek_position) self.set_position(after_seek_position)
#self.player.seek(amount) # self.player.seek(amount)
else: else:
self.message_handler.set_message('INFO', 'can not seek outside range') self.message_handler.set_message('INFO', 'can not seek outside range')
@@ -161,7 +160,7 @@ class VideoPlayer:
if (new_rate > self.omx_player.minimum_rate() and new_rate < self.omx_player.maximum_rate()): if (new_rate > self.omx_player.minimum_rate() and new_rate < self.omx_player.maximum_rate()):
updated_speed = self.omx_player.set_rate(new_rate) updated_speed = self.omx_player.set_rate(new_rate)
self.rate = new_rate self.rate = new_rate
print('max rate {} , min rate {} '.format(self.omx_player.maximum_rate() ,self.omx_player.minimum_rate())) print('max rate {} , min rate {} '.format(self.omx_player.maximum_rate(), self.omx_player.minimum_rate()))
return new_rate return new_rate
else: else:
self.message_handler.set_message('INFO', 'can not set speed outside of range') self.message_handler.set_message('INFO', 'can not set speed outside of range')
@@ -187,5 +186,3 @@ class VideoPlayer:
else: else:
aspect_mode = self.data.settings['video']['SCREEN_MODE']['value'] aspect_mode = self.data.settings['video']['SCREEN_MODE']['value']
return False, '--aspect-mode', aspect_mode return False, '--aspect-mode', aspect_mode