mirror of
https://github.com/cyberboy666/r_e_c_u_r.git
synced 2025-12-05 16:00:06 +01:00
Whitespace
This commit is contained in:
250
actions.py
250
actions.py
@@ -32,7 +32,7 @@ class Actions(object):
|
||||
self.remote_process = None
|
||||
self.set_capture_object('value')
|
||||
self.server = self.setup_osc_server()
|
||||
|
||||
|
||||
def set_capture_object(self, value):
|
||||
if self.data.settings['video']['VIDEOPLAYER_BACKEND']['value'] != 'omxplayer':
|
||||
self.python_capture.close_capture()
|
||||
@@ -54,7 +54,6 @@ class Actions(object):
|
||||
def move_browser_selection_page_up(self):
|
||||
self.display.browser_menu.navigate_menu_page_up()
|
||||
|
||||
|
||||
def enter_on_browser_selection(self):
|
||||
self.display.browser_menu.enter_on_browser_selection()
|
||||
|
||||
@@ -70,7 +69,6 @@ class Actions(object):
|
||||
def move_settings_selection_page_up(self):
|
||||
self.display.settings_menu.navigate_menu_page_up()
|
||||
|
||||
|
||||
def enter_on_settings_selection(self):
|
||||
is_setting, setting = self.display.settings_menu.enter_on_setting_selection()
|
||||
if is_setting:
|
||||
@@ -92,7 +90,6 @@ class Actions(object):
|
||||
def move_shaders_selection_page_up(self):
|
||||
self.shaders.shaders_menu.navigate_menu_page_up()
|
||||
|
||||
|
||||
def enter_on_shaders_selection(self):
|
||||
##want to select shader if its not selected, and want to enter 'param' mode if it already is
|
||||
is_shader, is_selected_shader, selected_shader = self.shaders.enter_on_shaders_selection()
|
||||
@@ -122,7 +119,7 @@ class Actions(object):
|
||||
self.display.browser_menu.generate_browser_list()
|
||||
|
||||
def _load_this_slot_into_next_player(self, slot):
|
||||
### load next player for seamless type otherwise respect player mode
|
||||
### load next player for seamless type otherwise respect player mode
|
||||
if self.data.settings['sampler']['LOOP_TYPE']['value'] == 'seamless':
|
||||
if self.data.update_next_slot_number(slot):
|
||||
print('should reload next player !! ')
|
||||
@@ -134,8 +131,6 @@ class Actions(object):
|
||||
else:
|
||||
if self.data.update_next_slot_number(slot, is_current=True):
|
||||
self.video_driver.reload_current_player()
|
||||
|
||||
|
||||
|
||||
def load_slot_0_into_next_player(self):
|
||||
self._load_this_slot_into_next_player(0)
|
||||
@@ -177,8 +172,8 @@ class Actions(object):
|
||||
|
||||
def set_display_mode(self, display_mode):
|
||||
mapmodes = {
|
||||
'shader': 'SHADERS',
|
||||
'shader_bank': 'SHDR_BNK'
|
||||
'shader': 'SHADERS',
|
||||
'shader_bank': 'SHDR_BNK'
|
||||
}
|
||||
if display_mode in mapmodes:
|
||||
display_mode = mapmodes[display_mode]
|
||||
@@ -186,7 +181,7 @@ class Actions(object):
|
||||
display_mode = display_mode.upper()
|
||||
|
||||
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:
|
||||
self.data.display_mode = display_modes[i][0]
|
||||
self.data.control_mode = display_modes[i][1]
|
||||
@@ -195,7 +190,7 @@ class Actions(object):
|
||||
display_modes = self.data.get_display_modes_list(with_nav_mode=True)
|
||||
|
||||
current_mode_index = [index for index, i in enumerate(display_modes) if self.data.display_mode in i][0]
|
||||
next_mode_index = (current_mode_index + 1) % len(display_modes)
|
||||
next_mode_index = (current_mode_index + 1) % len(display_modes)
|
||||
self.data.display_mode = display_modes[next_mode_index][0]
|
||||
self.data.control_mode = display_modes[next_mode_index][1]
|
||||
|
||||
@@ -203,11 +198,10 @@ class Actions(object):
|
||||
display_modes = self.data.get_display_modes_list(with_nav_mode=True)
|
||||
|
||||
current_mode_index = [index for index, i in enumerate(display_modes) if self.data.display_mode in i][0]
|
||||
next_mode_index = (current_mode_index - 1) % len(display_modes)
|
||||
next_mode_index = (current_mode_index - 1) % len(display_modes)
|
||||
self.data.display_mode = display_modes[next_mode_index][0]
|
||||
self.data.control_mode = display_modes[next_mode_index][1]
|
||||
|
||||
|
||||
def toggle_action_on_player(self):
|
||||
play = 'play' in self.data.settings['sampler']['ON_ACTION']['value']
|
||||
show = 'show' in self.data.settings['sampler']['ON_ACTION']['value']
|
||||
@@ -230,19 +224,17 @@ class Actions(object):
|
||||
|
||||
def increase_seek_time(self):
|
||||
options = self.data.settings['sampler']['SEEK_TIME']['options']
|
||||
current_index = [index for index, item in enumerate(options) if item == self.data.settings['sampler']['SEEK_TIME']['value'] ][0]
|
||||
self.data.update_setting_value('sampler', 'SEEK_TIME', options[(current_index + 1) % len(options) ])
|
||||
current_index = [index for index, item in enumerate(options) if item == self.data.settings['sampler']['SEEK_TIME']['value']][0]
|
||||
self.data.update_setting_value('sampler', 'SEEK_TIME', options[(current_index + 1) % len(options)])
|
||||
self.message_handler.set_message('INFO', 'The Seek Time is now ' + str(self.data.settings['sampler']['SEEK_TIME']['value']) + 's')
|
||||
|
||||
|
||||
def decrease_seek_time(self):
|
||||
options = self.data.settings['sampler']['SEEK_TIME']['options']
|
||||
current_index = [index for index, item in enumerate(options) if item == self.data.settings['sampler']['SEEK_TIME']['value'] ][0]
|
||||
self.data.update_setting_value('sampler', 'SEEK_TIME', options[(current_index - 1) % len(options) ])
|
||||
current_index = [index for index, item in enumerate(options) if item == self.data.settings['sampler']['SEEK_TIME']['value']][0]
|
||||
self.data.update_setting_value('sampler', 'SEEK_TIME', options[(current_index - 1) % len(options)])
|
||||
self.message_handler.set_message('INFO', 'The Seek Time is now ' + str(self.data.settings['sampler']['SEEK_TIME']['value']) + 's')
|
||||
|
||||
|
||||
def seek_forward_on_player(self):
|
||||
def seek_forward_on_player(self):
|
||||
self.video_driver.current_player.seek(self.data.settings['sampler']['SEEK_TIME']['value'])
|
||||
|
||||
def seek_back_on_player(self):
|
||||
@@ -264,24 +256,24 @@ class Actions(object):
|
||||
def previous_bank(self):
|
||||
self.data.update_bank_number_by_amount(-1)
|
||||
print('current bank is {} , the number of banks is {} '.format(self.data.bank_number, len(self.data.bank_data)))
|
||||
|
||||
|
||||
def increase_speed(self):
|
||||
print("increasing speed !")
|
||||
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)
|
||||
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):
|
||||
print("increasing speed !")
|
||||
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)
|
||||
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):
|
||||
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._load_this_slot_into_next_player(current_slot)
|
||||
|
||||
@@ -292,7 +284,7 @@ class Actions(object):
|
||||
|
||||
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_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._load_this_slot_into_next_player(current_slot)
|
||||
|
||||
@@ -305,19 +297,18 @@ class Actions(object):
|
||||
is_previewing = self.capture.is_previewing
|
||||
if is_previewing:
|
||||
self.capture.stop_preview()
|
||||
#if self.video_driver.current_player.status == 'PAUSED':
|
||||
#self.video_driver.current_player.toggle_pause()
|
||||
# if self.video_driver.current_player.status == 'PAUSED':
|
||||
# self.video_driver.current_player.toggle_pause()
|
||||
else:
|
||||
is_successful = self.capture.start_preview()
|
||||
#if is_successful and self.video_driver.current_player.status != 'PAUSED':
|
||||
#self.video_driver.current_player.toggle_pause()
|
||||
|
||||
# if is_successful and self.video_driver.current_player.status != 'PAUSED':
|
||||
# self.video_driver.current_player.toggle_pause()
|
||||
|
||||
def toggle_capture_recording(self):
|
||||
is_recording = self.capture.is_recording
|
||||
if is_recording:
|
||||
self.capture.stop_recording()
|
||||
else:
|
||||
else:
|
||||
self.capture.start_recording()
|
||||
|
||||
def toggle_screen_mirror(self):
|
||||
@@ -360,12 +351,12 @@ class Actions(object):
|
||||
self.data.detour_active = True
|
||||
shader_input = self.data.settings['detour']['SHADER_POSITION']['value'] == 'input'
|
||||
self.video_driver.osc_client.send_message("/detour/start", shader_input)
|
||||
self.load_this_detour_shader()
|
||||
self.load_this_detour_shader()
|
||||
|
||||
def toggle_detour_play(self):
|
||||
if self.data.settings['detour']['TRY_DEMO']['value'] == 'enabled':
|
||||
is_playing = not self.data.detour_settings['is_playing']
|
||||
self.data.detour_settings['is_playing'] = is_playing
|
||||
is_playing = not self.data.detour_settings['is_playing']
|
||||
self.data.detour_settings['is_playing'] = is_playing
|
||||
self.video_driver.osc_client.send_message("/detour/is_playing", is_playing)
|
||||
|
||||
def toggle_feedback(self):
|
||||
@@ -432,14 +423,14 @@ class Actions(object):
|
||||
|
||||
def toggle_detour_record(self):
|
||||
if self.data.settings['detour']['TRY_DEMO']['value'] == 'enabled':
|
||||
is_recording = not self.data.detour_settings['is_recording']
|
||||
self.data.detour_settings['is_recording'] = is_recording
|
||||
is_recording = not self.data.detour_settings['is_recording']
|
||||
self.data.detour_settings['is_recording'] = is_recording
|
||||
self.video_driver.osc_client.send_message("/detour/is_recording", is_recording)
|
||||
|
||||
def toggle_detour_record_loop(self):
|
||||
if self.data.settings['detour']['TRY_DEMO']['value'] == 'enabled':
|
||||
record_loop = not self.data.detour_settings['record_loop']
|
||||
self.data.detour_settings['record_loop'] = record_loop
|
||||
self.data.detour_settings['record_loop'] = record_loop
|
||||
self.video_driver.osc_client.send_message("/detour/record_loop", record_loop)
|
||||
|
||||
def clear_this_detour(self):
|
||||
@@ -477,10 +468,9 @@ class Actions(object):
|
||||
|
||||
def switch_to_this_detour(self, number):
|
||||
if self.data.settings['detour']['TRY_DEMO']['value'] == 'enabled':
|
||||
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)
|
||||
|
||||
|
||||
def set_detour_delay_mode(self, state):
|
||||
self.video_driver.osc_client.send_message("/detour/set_delay_mode", state == 'enabled')
|
||||
self.data.update_conjur_delay_mode(state == 'enabled')
|
||||
@@ -513,19 +503,19 @@ class Actions(object):
|
||||
self.set_detour_mix_continuous(1)
|
||||
|
||||
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):
|
||||
self.capture.set_colour(None, amount*255)
|
||||
self.capture.set_colour(None, amount * 255)
|
||||
|
||||
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):
|
||||
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):
|
||||
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):
|
||||
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)
|
||||
|
||||
def get_midi_status(self):
|
||||
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))
|
||||
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))
|
||||
|
||||
def cycle_midi_port_index(self):
|
||||
self.data.midi_port_index = self.data.midi_port_index + 1
|
||||
@@ -629,24 +619,23 @@ class Actions(object):
|
||||
self.data.update_setting_value('video', 'OUTPUT', 'hdmi')
|
||||
|
||||
if self.data.settings['video']['HDMI_MODE']['value'] == "CEA 4 HDMI":
|
||||
|
||||
|
||||
self.data.update_setting_value('video', 'HDMI_MODE', 'CEA 4 HDMI')
|
||||
|
||||
self.change_hdmi_settings('CEA 4 HDMI')
|
||||
|
||||
|
||||
def check_dev_mode(self):
|
||||
#### check if in dev mode:(ie not using the lcd screen)
|
||||
with open('/boot/config.txt', 'r') as config:
|
||||
if '##no_waveshare_overlay' in config.read():
|
||||
self.data.update_setting_value('system','DEV_MODE_RESET', 'on')
|
||||
else:
|
||||
self.data.update_setting_value('system','DEV_MODE_RESET', 'off')
|
||||
if '##no_waveshare_overlay' in config.read():
|
||||
self.data.update_setting_value('system', 'DEV_MODE_RESET', 'on')
|
||||
else:
|
||||
self.data.update_setting_value('system', 'DEV_MODE_RESET', 'off')
|
||||
|
||||
def check_if_should_start_openframeworks(self):
|
||||
if self.data.settings['video']['VIDEOPLAYER_BACKEND']['value'] != 'omxplayer':
|
||||
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)
|
||||
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)
|
||||
print('conjur pid is {}'.format(self.openframeworks_process.pid))
|
||||
|
||||
def exit_openframeworks(self):
|
||||
@@ -669,7 +658,7 @@ class Actions(object):
|
||||
self.set_capture_object('nothing')
|
||||
self.display.settings_menu.generate_settings_list()
|
||||
self.reset_players()
|
||||
|
||||
|
||||
def reset_players(self):
|
||||
self.video_driver.reset_all_players()
|
||||
|
||||
@@ -680,16 +669,15 @@ class Actions(object):
|
||||
progressive = ''
|
||||
if self.data.settings['video']['COMPOSITE_PROGRESSIVE']['value'] == 'on':
|
||||
progressive = 'p'
|
||||
|
||||
|
||||
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.persist_composite_setting(mode, progressive, aspect)
|
||||
|
||||
|
||||
def _refresh_frame_buffer(self):
|
||||
self.data.open_omxplayer_for_reset()
|
||||
subprocess.run(["fbset -depth 16; fbset -depth 32; xrefresh -display :0" ], shell=True)
|
||||
subprocess.run(["fbset -depth 16; fbset -depth 32; xrefresh -display :0"], shell=True)
|
||||
|
||||
def persist_composite_setting(self, mode, progressive, aspect):
|
||||
sdtv_mode = ''
|
||||
@@ -714,7 +702,7 @@ class Actions(object):
|
||||
self.update_config_settings(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):
|
||||
if state == 'on':
|
||||
@@ -727,13 +715,12 @@ class Actions(object):
|
||||
self.switch_display_to_lcd()
|
||||
|
||||
def switch_display_to_hdmi(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:
|
||||
if 'dtoverlay=waveshare35a:rotate=270' in config.read() and 'dev/fb1' in framebuffer_conf.read():
|
||||
self.run_script('switch_display_to_hdmi')
|
||||
else:
|
||||
self.message_handler.set_message('INFO', 'failed to switch display')
|
||||
|
||||
|
||||
def switch_display_to_lcd(self):
|
||||
with open('/boot/config.txt', 'r') as config:
|
||||
@@ -745,9 +732,9 @@ class Actions(object):
|
||||
self.message_handler.set_message('INFO', 'failed to switch display')
|
||||
|
||||
def run_script(self, script_name, 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 ])
|
||||
|
||||
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])
|
||||
|
||||
def toggle_x_autorepeat(self):
|
||||
if self.data.auto_repeat_on:
|
||||
subprocess.call(['xset', 'r', 'off'])
|
||||
@@ -756,13 +743,12 @@ class Actions(object):
|
||||
subprocess.call(['xset', 'r', 'on'])
|
||||
self.data.auto_repeat_on = True
|
||||
|
||||
|
||||
def quit_the_program(self):
|
||||
self.data._update_json(self.data.SETTINGS_JSON, self.data.settings)
|
||||
self.data.plugins.quit_plugins()
|
||||
self.video_driver.exit_all_players()
|
||||
self.exit_openframeworks()
|
||||
self.exit_osc_server('','')
|
||||
self.exit_osc_server('', '')
|
||||
self.create_client_and_shutdown_osc_server()
|
||||
self.stop_serial_port_process()
|
||||
self.stop_openframeworks_process()
|
||||
@@ -772,8 +758,8 @@ class Actions(object):
|
||||
|
||||
def restart_the_program(self):
|
||||
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):
|
||||
self.data.control_mode = 'SHADER_PARAM'
|
||||
self.message_handler.set_message('INFO', '[ ]: focus < >: level ■: back')
|
||||
@@ -786,21 +772,21 @@ class Actions(object):
|
||||
self.shaders.decrease_this_param(self.data.settings['shader']['SHADER_PARAM']['value'])
|
||||
|
||||
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):
|
||||
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):
|
||||
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]
|
||||
self.data.update_setting_value('shader', 'SHADER_PARAM', options[(current_index + 1) % len(options) ])
|
||||
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.message_handler.set_message('INFO', 'The Param amount is now ' + str(self.data.settings['shader']['SHADER_PARAM']['value']))
|
||||
|
||||
def decrease_shader_param(self):
|
||||
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]
|
||||
self.data.update_setting_value('shader', 'SHADER_PARAM', options[(current_index - 1) % len(options) ])
|
||||
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.message_handler.set_message('INFO', 'The Param amount is now ' + str(self.data.settings['shader']['SHADER_PARAM']['value']))
|
||||
|
||||
def set_fixed_length(self, value):
|
||||
@@ -808,12 +794,11 @@ class Actions(object):
|
||||
self.message_handler.set_message('INFO', 'tap: ■ ; < > : back')
|
||||
self.fixed_length_setter = length_setter.FixedLengthSetter(self.data)
|
||||
|
||||
|
||||
def return_to_default_control_mode(self):
|
||||
display_list = self.data.get_display_modes_list(with_nav_mode=True)
|
||||
for display, control in display_list:
|
||||
if display == self.data.display_mode:
|
||||
self.data.control_mode = control
|
||||
self.data.control_mode = control
|
||||
|
||||
def perform_confirm_action(self):
|
||||
action = self.data.confirm_action
|
||||
@@ -829,10 +814,10 @@ class Actions(object):
|
||||
self.message_handler.set_message('INFO', 'confirm: {} ■:y < >:no'.format(action_title[:22]))
|
||||
|
||||
def confirm_shutdown(self):
|
||||
self.start_confirm_action('shutdown_pi' )
|
||||
self.start_confirm_action('shutdown_pi')
|
||||
|
||||
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):
|
||||
# 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.display.settings_menu.generate_settings_list()
|
||||
|
||||
|
||||
def setup_osc_server(self):
|
||||
server_parser = argparse.ArgumentParser()
|
||||
server_parser.add_argument("--ip", default="127.0.0.1", help="the ip")
|
||||
@@ -861,7 +845,7 @@ class Actions(object):
|
||||
this_dispatcher.map("/detour/detour_info", self.receive_detour_info)
|
||||
this_dispatcher.map("/capture/recording_finished", self.capture.receive_recording_finished)
|
||||
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
|
||||
server = osc_server.ThreadingOSCUDPServer((server_args.ip, server_args.port), this_dispatcher)
|
||||
@@ -889,10 +873,10 @@ class Actions(object):
|
||||
|
||||
def toggle_access_point(self, setting_value):
|
||||
osc_setting_state = self.data.settings['user_input']['OSC_INPUT']['value']
|
||||
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)
|
||||
|
||||
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':
|
||||
subprocess.call(['sudo', 'bash', '/home/pi/raspiApWlanScripts/switchToAP.sh'])
|
||||
else:
|
||||
@@ -914,7 +898,6 @@ class Actions(object):
|
||||
def enable_osc(self, osc_setting_state):
|
||||
self.data.update_setting_value('user_input', 'OSC_INPUT', osc_setting_state)
|
||||
|
||||
|
||||
def show_ip(self, *args):
|
||||
address = self.data.get_ip_address()
|
||||
self.message_handler.set_message('INFO', 'ip is {}:8080'.format(address))
|
||||
@@ -922,14 +905,13 @@ class Actions(object):
|
||||
def create_serial_port_process(self):
|
||||
if self.serial_port_process == None:
|
||||
self.serial_port_process = subprocess.Popen("exec " + "ttymidi -s /dev/serial0 -b 38400 -n serial", shell=True)
|
||||
print('created the serial port process ? {}'.format(self.serial_port_process))
|
||||
print('created the serial port process ? {}'.format(self.serial_port_process))
|
||||
|
||||
def stop_serial_port_process(self):
|
||||
if self.serial_port_process is not None:
|
||||
self.serial_port_process.kill()
|
||||
self.serial_port_process = None
|
||||
|
||||
|
||||
def stop_remote_process(self):
|
||||
if self.remote_process is not None:
|
||||
self.remote_process.kill()
|
||||
@@ -939,7 +921,7 @@ class Actions(object):
|
||||
self.reset_players()
|
||||
self.exit_openframeworks()
|
||||
self.stop_openframeworks_process()
|
||||
self.check_if_should_start_openframeworks()
|
||||
self.check_if_should_start_openframeworks()
|
||||
|
||||
def refresh_frame_buffer_and_restart_openframeworks(self):
|
||||
if self.data.settings['video']['VIDEOPLAYER_BACKEND']['value'] != 'omxplayer':
|
||||
@@ -948,7 +930,7 @@ class Actions(object):
|
||||
self.stop_openframeworks_process()
|
||||
self._refresh_frame_buffer()
|
||||
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:
|
||||
self._refresh_frame_buffer()
|
||||
|
||||
@@ -960,21 +942,21 @@ class Actions(object):
|
||||
subprocess.call(['killall', 'c_o_n_j_u_r'])
|
||||
|
||||
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")
|
||||
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")
|
||||
current_recur_hash = recur_repo.head.object.hexsha
|
||||
current_conjur_hash = conjur_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_DEFAULT_CONJUR_DATA)
|
||||
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)
|
||||
try:
|
||||
recur_repo.remotes.origin.pull()
|
||||
conjur_repo.remotes.origin.pull()
|
||||
ofxVideoArtTools_repo.remotes.origin.pull()
|
||||
except git.exc.GitCommandError as e:
|
||||
except git.exc.GitCommandError as e:
|
||||
if 'unable to access' in str(e):
|
||||
self.message_handler.set_message('INFO', 'not connected to network')
|
||||
else:
|
||||
@@ -982,22 +964,22 @@ class Actions(object):
|
||||
error_info = e.message
|
||||
else:
|
||||
error_info = e
|
||||
self.message_handler.set_message('ERROR',error_info)
|
||||
self.message_handler.set_message('ERROR', error_info)
|
||||
return
|
||||
|
||||
|
||||
new_recur_hash = recur_repo.head.object.hexsha
|
||||
new_conjur_hash = conjur_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 :
|
||||
#something has changed!
|
||||
if current_recur_hash != new_recur_hash or current_conjur_hash != new_conjur_hash or current_ofxVideoArtTools_hash != new_ofxVideoArtTools_hash:
|
||||
# something has changed!
|
||||
self.restart_the_program()
|
||||
else:
|
||||
self.message_handler.set_message('INFO', 'up to date !')
|
||||
|
||||
# def complie_openframeworks(self):
|
||||
# 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.restart_the_program()
|
||||
# def complie_openframeworks(self):
|
||||
# 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.restart_the_program()
|
||||
|
||||
def shutdown_pi(self):
|
||||
subprocess.call(['sudo', 'shutdown', '-h', 'now'])
|
||||
@@ -1005,7 +987,7 @@ class Actions(object):
|
||||
def clear_message(self):
|
||||
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)"""
|
||||
|
||||
@staticmethod
|
||||
@@ -1016,35 +998,34 @@ class Actions(object):
|
||||
def eject_all_usb_drives(self):
|
||||
for i in range(1, 4):
|
||||
if os.path.exists('/dev/sda{}'.format(i)):
|
||||
subprocess.call(['sudo', 'eject', '/dev/sda{}'.format(i)])
|
||||
subprocess.call(['sudo', 'eject', '/dev/sda{}'.format(i)])
|
||||
self.message_handler.set_message('INFO', 'usb ejected')
|
||||
|
||||
|
||||
# TODO: make this interrogate the various components for available routes to parse
|
||||
# this would include eg a custom script module..
|
||||
@property
|
||||
def parserlist(self):
|
||||
return {
|
||||
( r"^play_shader_([0-9])_([0-9])$", self.shaders.play_that_shader ),
|
||||
( r"^toggle_shader_layer_([0-2])$", self.toggle_shader_layer ),
|
||||
( r"^start_shader_layer_([0-2])$", self.shaders.start_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"^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_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_modulation_([0-3])$", self.shaders.reset_modulation ),
|
||||
( 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_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_([0-2])_amount$", self.shaders.set_speed_layer_to_amount ),
|
||||
( r"^set_display_mode_([a-zA-Z_]*)$", self.set_display_mode )
|
||||
(r"^play_shader_([0-9])_([0-9])$", self.shaders.play_that_shader),
|
||||
(r"^toggle_shader_layer_([0-2])$", self.toggle_shader_layer),
|
||||
(r"^start_shader_layer_([0-2])$", self.shaders.start_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"^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_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_modulation_([0-3])$", self.shaders.reset_modulation),
|
||||
(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_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_([0-2])_amount$", self.shaders.set_speed_layer_to_amount),
|
||||
(r"^set_display_mode_([a-zA-Z_]*)$", self.set_display_mode)
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
def get_callback_for_method(self, method_name, argument):
|
||||
@@ -1054,13 +1035,13 @@ class Actions(object):
|
||||
matches = re.search(regex, method_name)
|
||||
|
||||
if matches:
|
||||
found_method = me
|
||||
parsed_args = self.detect_types(matches.groups()) #list(map(int,matches.groups()))
|
||||
found_method = me
|
||||
parsed_args = self.detect_types(matches.groups()) # list(map(int,matches.groups()))
|
||||
if argument is not None:
|
||||
args = parsed_args + [argument]
|
||||
else:
|
||||
args = parsed_args
|
||||
|
||||
args = parsed_args
|
||||
|
||||
return (found_method, args)
|
||||
|
||||
return None, None
|
||||
@@ -1072,7 +1053,7 @@ class Actions(object):
|
||||
# first check if we have a native method to handle this for us
|
||||
# todo: assess whether it would still be performant/desirable to be able to override core actions with plugins?
|
||||
if hasattr(self, method_name):
|
||||
|
||||
|
||||
method = getattr(self, method_name)
|
||||
if argument is not None:
|
||||
arguments = [argument]
|
||||
@@ -1089,29 +1070,28 @@ class Actions(object):
|
||||
from data_centre.plugin_collection import ActionsPlugin
|
||||
for plugin in self.data.plugins.get_plugins(ActionsPlugin):
|
||||
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)
|
||||
break # only deal with the first plugin
|
||||
break # only deal with the first plugin
|
||||
|
||||
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
|
||||
traceback.print_exc()
|
||||
return
|
||||
|
||||
try:
|
||||
#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
|
||||
#print(type(argument))
|
||||
# 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
|
||||
# print(type(argument))
|
||||
if len(signature(method).parameters) == 0 and isinstance(argument, float) and argument == 0:
|
||||
print('cc off ?')
|
||||
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)
|
||||
else:
|
||||
method()
|
||||
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
|
||||
traceback.print_exc()
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ class AsyncWrite(threading.Thread):
|
||||
|
||||
def run(self):
|
||||
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)
|
||||
else:
|
||||
data_file.write(self.data)
|
||||
@@ -29,7 +29,6 @@ class AsyncWrite(threading.Thread):
|
||||
|
||||
|
||||
class Data(object):
|
||||
|
||||
BANK_DATA_JSON = 'display_data.json'
|
||||
SHADER_BANK_DATA_JSON = 'shader_bank_data.json'
|
||||
SETTINGS_JSON = 'settings.json'
|
||||
@@ -48,11 +47,11 @@ class Data(object):
|
||||
|
||||
def __init__(self, message_handler):
|
||||
self.message_handler = message_handler
|
||||
|
||||
#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_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.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_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]
|
||||
|
||||
### state data
|
||||
self.auto_repeat_on = True
|
||||
@@ -66,20 +65,20 @@ class Data(object):
|
||||
self.update_screen = True
|
||||
self.confirm_action = None
|
||||
self.player_mode = 'now'
|
||||
|
||||
|
||||
self.feedback_active = False
|
||||
self.detour_active = False
|
||||
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.current_bankslot = '0-0'
|
||||
|
||||
|
||||
self.shader_layer = 0
|
||||
|
||||
|
||||
### persisted data (use default if doesnt exits):
|
||||
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)
|
||||
|
||||
self.bank_data = [self.create_empty_bank()]
|
||||
@@ -99,7 +98,7 @@ class Data(object):
|
||||
if os.path.isfile(self.PATH_TO_DATA_OBJECTS + self.SETTINGS_JSON):
|
||||
self.settings = self._read_json(self.SETTINGS_JSON)
|
||||
self.settings['user_input'].setdefault('REMOTE_SERVER',
|
||||
self.default_settings['user_input']['REMOTE_SERVER'])['value'] = 'disabled' # remote server off at boot
|
||||
self.default_settings['user_input']['REMOTE_SERVER'])['value'] = 'disabled' # remote server off at boot
|
||||
|
||||
self.key_mappings = self._read_json(self.KEYPAD_MAPPING_JSON)
|
||||
self.osc_mappings = self._read_json(self.OSC_MAPPING_JSON)
|
||||
@@ -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("Analog mappings", self.analog_mappings, column_one_header="Analogue input")
|
||||
docs.generate_mappings_doc("Key mappings", self.key_mappings, column_one_header="Key mappings")
|
||||
#quit()
|
||||
# quit()
|
||||
|
||||
def initialise_plugins(self):
|
||||
#initialise plugin manager
|
||||
# initialise plugin manager
|
||||
self.plugins = plugin_collection.PluginCollection("plugins", self.message_handler, self)
|
||||
self.compare_plugins_list()
|
||||
|
||||
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):
|
||||
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)
|
||||
for k in plugins_to_add:
|
||||
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':
|
||||
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):
|
||||
self.enabled_plugins[key] = value
|
||||
@@ -141,16 +140,16 @@ class Data(object):
|
||||
|
||||
def load_midi_mapping_for_device(self, 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):
|
||||
self.midi_mappings = self._read_json(custom_file)
|
||||
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:
|
||||
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)
|
||||
return self.midi_mappings
|
||||
|
||||
|
||||
def get_ip_address(self):
|
||||
ip_list = subprocess.check_output(['hostname', '-I']).decode('utf-8').split()
|
||||
if len(ip_list) > 0:
|
||||
@@ -163,7 +162,7 @@ class Data(object):
|
||||
return '127.0.0.1'
|
||||
else:
|
||||
return self.get_ip_address()
|
||||
|
||||
|
||||
@staticmethod
|
||||
def create_empty_bank():
|
||||
empty_slot = dict(name='', location='', length=-1, start=-1, end=-1, rate=1)
|
||||
@@ -173,7 +172,7 @@ class Data(object):
|
||||
def create_empty_shader_bank():
|
||||
empty_slot = dict(name='', path='', param_number=4, shad_type='-')
|
||||
return [empty_slot for i in range(10)]
|
||||
|
||||
|
||||
def _read_json(self, file_name):
|
||||
with open(self.PATH_TO_DATA_OBJECTS + file_name) as data_file:
|
||||
data = json.load(data_file)
|
||||
@@ -187,15 +186,15 @@ class Data(object):
|
||||
for path in self.PATHS_TO_PLUGIN_DATA:
|
||||
print("loading plugin data %s" % path)
|
||||
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)
|
||||
return data
|
||||
except:
|
||||
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):
|
||||
#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)
|
||||
writer = AsyncWrite("%s/%s" % (self.PATHS_TO_PLUGIN_DATA[0], file_name), data, mode='json')
|
||||
writer.start()
|
||||
@@ -220,12 +219,12 @@ class Data(object):
|
||||
tree.write(self.PATH_TO_CONJUR_DATA)
|
||||
|
||||
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():
|
||||
if setting_key == setting_name:
|
||||
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):
|
||||
######## 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):
|
||||
######## used for mapping current video to a specific slot ########
|
||||
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)
|
||||
if length:
|
||||
new_slot = dict(name=file_name, location=location, length=length, start=-1, end=-1, rate=1)
|
||||
@@ -250,15 +249,15 @@ class Data(object):
|
||||
|
||||
def update_bank_number_by_amount(self, amount):
|
||||
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)
|
||||
elif(len(self.bank_data) > 1):
|
||||
elif (len(self.bank_data) > 1):
|
||||
if self.bank_data[-2] == empty_bank:
|
||||
self.bank_data.pop()
|
||||
self._update_json(self.BANK_DATA_JSON, 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):
|
||||
self.bank_number = (self.bank_number + amount) % (len(self.bank_data))
|
||||
|
||||
def update_next_slot_number(self, new_value, is_current=False):
|
||||
if self.bank_data[self.bank_number][new_value]['location'] == '':
|
||||
self.message_handler.set_message('INFO', 'the slot you pressed is empty')
|
||||
return False
|
||||
@@ -266,14 +265,13 @@ class Data(object):
|
||||
self.message_handler.set_message('INFO', 'no device found for this slot')
|
||||
return False
|
||||
elif is_current:
|
||||
self.current_bankslot = '{}-{}'.format(self.bank_number,new_value)
|
||||
self.current_bankslot = '{}-{}'.format(self.bank_number, new_value)
|
||||
return True
|
||||
else:
|
||||
self.next_bankslot = '{}-{}'.format(self.bank_number,new_value)
|
||||
self.next_bankslot = '{}-{}'.format(self.bank_number, new_value)
|
||||
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):
|
||||
######## used for mapping current shader to next available slot ########
|
||||
@@ -286,7 +284,7 @@ class Data(object):
|
||||
def create_new_shader_mapping(self, slot_number, file_name):
|
||||
######## used for mapping current shader to a specific slot ########
|
||||
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)
|
||||
self._update_a_shader_slots_data(slot_number, new_slot)
|
||||
|
||||
@@ -295,28 +293,26 @@ class Data(object):
|
||||
self._update_json(self.SHADER_BANK_DATA_JSON, self.shader_bank_data)
|
||||
|
||||
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):
|
||||
self.settings[setting_folder][setting_name]['value'] = setting_value
|
||||
self._update_json(self.SETTINGS_JSON, self.settings)
|
||||
return self.settings[setting_folder][setting_name]
|
||||
|
||||
|
||||
@classmethod
|
||||
def split_bankslot_number(cls, bankslot_number):
|
||||
split = bankslot_number.split('-')
|
||||
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_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])
|
||||
return converted_bank_number, converted_slot_number
|
||||
|
||||
@staticmethod
|
||||
def try_convert_string_to_int(string_input):
|
||||
try:
|
||||
return True , int(string_input)
|
||||
return True, int(string_input)
|
||||
except ValueError:
|
||||
return False , '*'
|
||||
return False, '*'
|
||||
|
||||
def get_next_context(self, is_current=False):
|
||||
######## loads the slot details, uses settings to modify them and then set next slot number ########
|
||||
@@ -324,14 +320,14 @@ class Data(object):
|
||||
bankslot_number = self.current_bankslot
|
||||
else:
|
||||
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]
|
||||
start_value = next_slot_details['start']
|
||||
end_value = next_slot_details['end']
|
||||
length = next_slot_details['length']
|
||||
|
||||
start_value, end_value = self._overwrite_values_with_sampler_settings(start_value, end_value, length)
|
||||
start_value, end_value = self._overwrite_values_with_sampler_settings(start_value, end_value, length)
|
||||
|
||||
context = dict(location=next_slot_details['location'], name=next_slot_details['name'],
|
||||
length=next_slot_details['length'], rate=next_slot_details['rate'], start=start_value, end=end_value,
|
||||
@@ -347,22 +343,22 @@ class Data(object):
|
||||
fixed_length_multiply = self.settings['sampler']['FIXED_LENGTH_MULTIPLY']['value']
|
||||
total_fixed_length = fixed_length_value * fixed_length_multiply
|
||||
if start == -1:
|
||||
start = 0
|
||||
start = 0
|
||||
if end == -1:
|
||||
end = length
|
||||
end = length
|
||||
new_end = end
|
||||
new_start = start
|
||||
|
||||
if use_fixed_length and use_rand_start:
|
||||
max_increase = int(max(end - start - max(total_fixed_length, 4),0))
|
||||
random_increase = randint(0,max_increase)
|
||||
max_increase = int(max(end - start - max(total_fixed_length, 4), 0))
|
||||
random_increase = randint(0, max_increase)
|
||||
new_start = start + random_increase
|
||||
new_end = min(new_start + total_fixed_length, end)
|
||||
elif use_fixed_length and not use_rand_start:
|
||||
new_end = min(new_start + total_fixed_length, end)
|
||||
elif not use_fixed_length and use_rand_start:
|
||||
max_increase = int(max(end - start - 4,0))
|
||||
random_increase = randint(0,max_increase)
|
||||
max_increase = int(max(end - start - 4, 0))
|
||||
random_increase = randint(0, max_increase)
|
||||
new_start = start + random_increase
|
||||
|
||||
return new_start, new_end
|
||||
@@ -372,17 +368,17 @@ class Data(object):
|
||||
loaded_slots = self._get_list_of_loaded_slots_in_current_bank()
|
||||
if loaded_slots:
|
||||
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':
|
||||
next_slot = self.get_next_loaded_slot(slot_num, loaded_slots)
|
||||
else:
|
||||
next_slot = slot_num
|
||||
|
||||
if is_current:
|
||||
self.current_bankslot = '{}-{}'.format(self.bank_number,next_slot)
|
||||
self.current_bankslot = '{}-{}'.format(self.bank_number, next_slot)
|
||||
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):
|
||||
list_of_loaded_slots = []
|
||||
for index, slot in enumerate(self.bank_data[self.bank_number]):
|
||||
@@ -392,9 +388,9 @@ class Data(object):
|
||||
|
||||
@staticmethod
|
||||
def get_next_loaded_slot(current_slot, loaded_slots):
|
||||
i = ( current_slot + 1 ) % len(loaded_slots)
|
||||
while(i not in loaded_slots):
|
||||
i = ( i + 1 ) % len(loaded_slots)
|
||||
i = (current_slot + 1) % len(loaded_slots)
|
||||
while (i not in loaded_slots):
|
||||
i = (i + 1) % len(loaded_slots)
|
||||
return i
|
||||
|
||||
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)
|
||||
|
||||
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):
|
||||
try:
|
||||
@@ -419,62 +415,60 @@ class Data(object):
|
||||
temp_player.quit()
|
||||
return duration
|
||||
except Exception as e:
|
||||
print (e)
|
||||
print(e)
|
||||
if not no_message:
|
||||
self.message_handler.set_message('INFO', 'cannot load video')
|
||||
return None
|
||||
|
||||
|
||||
def _get_path_for_file(self, file_name):
|
||||
######## returns full path for a given file name ########
|
||||
for path in self.PATHS_TO_BROWSER + self.PATHS_TO_SHADERS:
|
||||
for path in self.PATHS_TO_BROWSER + self.PATHS_TO_SHADERS:
|
||||
for root, dirs, files in os.walk(path):
|
||||
if file_name in files:
|
||||
return True, '{}/{}'.format(root, file_name)
|
||||
return False, ''
|
||||
|
||||
|
||||
def is_this_path_broken(self, path):
|
||||
external_devices = os.listdir(self.PATH_TO_EXTERNAL_DEVICES)
|
||||
has_device_in_path = self.PATH_TO_EXTERNAL_DEVICES in path
|
||||
has_existing_device_in_path = any([(x in path) for x in external_devices])
|
||||
|
||||
if has_device_in_path and not has_existing_device_in_path:
|
||||
|
||||
if has_device_in_path and not has_existing_device_in_path:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def get_background_colour(self):
|
||||
colour_name = self.settings['video']['BACKGROUND_COLOUR']['value']
|
||||
colour_argb = (255,0,0,0)
|
||||
colour_argb = (255, 0, 0, 0)
|
||||
if colour_name == "black":
|
||||
colour_argb = (255,0,0,0)
|
||||
colour_argb = (255, 0, 0, 0)
|
||||
elif colour_name == "white":
|
||||
colour_argb = (255,255,255,255)
|
||||
colour_argb = (255, 255, 255, 255)
|
||||
elif colour_name == "green":
|
||||
colour_argb = (255,0,255,0)
|
||||
colour_argb = (255, 0, 255, 0)
|
||||
elif colour_name == "blue":
|
||||
colour_argb = (255,0,0,255)
|
||||
colour_argb = (255, 0, 0, 255)
|
||||
elif colour_name == "pink":
|
||||
colour_argb = (255,255,0,255)
|
||||
colour_argb = (255, 255, 0, 255)
|
||||
elif colour_name == "none":
|
||||
colour_argb = (0,0,0,0)
|
||||
colour_argb = (0, 0, 0, 0)
|
||||
colour_hex = '%02x%02x%02x%02x' % colour_argb
|
||||
return colour_hex
|
||||
|
||||
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':
|
||||
display_modes.append(["SHADERS",'NAV_SHADERS'])
|
||||
if self.settings['shader']['USE_SHADER_BANK']['value'] == 'enabled' and ["SHADERS",'NAV_SHADERS'] in display_modes:
|
||||
display_modes.append(["SHDR_BNK",'PLAY_SHADER'])
|
||||
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(["SHADERS", 'NAV_SHADERS'])
|
||||
if self.settings['shader']['USE_SHADER_BANK']['value'] == 'enabled' and ["SHADERS", 'NAV_SHADERS'] in display_modes:
|
||||
display_modes.append(["SHDR_BNK", 'PLAY_SHADER'])
|
||||
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
|
||||
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',
|
||||
self.default_settings.setdefault('USE_PLUGINS',{'value': 'enabled'})).get('value') == 'enabled':
|
||||
display_modes.append(["PLUGINS",'NAV_PLUGINS'])
|
||||
self.default_settings.setdefault('USE_PLUGINS', {'value': 'enabled'})).get('value') == 'enabled':
|
||||
display_modes.append(["PLUGINS", 'NAV_PLUGINS'])
|
||||
|
||||
if hasattr(self, 'plugins') and self.plugins is not None:
|
||||
from data_centre.plugin_collection import DisplayPlugin
|
||||
@@ -499,7 +493,7 @@ class Data(object):
|
||||
######## overwrite a given slots info with new data ########
|
||||
self.shader_bank_data[self.shader_layer][slot_number] = slot_info
|
||||
self._update_json(self.SHADER_BANK_DATA_JSON, self.shader_bank_data)
|
||||
|
||||
|
||||
@staticmethod
|
||||
def make_empty_if_none(input):
|
||||
if input is None:
|
||||
@@ -512,15 +506,13 @@ class Data(object):
|
||||
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'))
|
||||
return filenames
|
||||
#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'))
|
||||
#return filenames
|
||||
# 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'))
|
||||
# return filenames
|
||||
else:
|
||||
return []
|
||||
|
||||
return []
|
||||
|
||||
@staticmethod
|
||||
def try_remove_file(path):
|
||||
if os.path.exists(path):
|
||||
os.remove(path)
|
||||
|
||||
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
import datetime
|
||||
|
||||
|
||||
class FixedLengthSetter(object):
|
||||
DELTA_NUMBER = 2
|
||||
DELTA_NUMBER = 2
|
||||
|
||||
def __init__(self, data):
|
||||
self.data = data
|
||||
|
||||
self.last_time = None
|
||||
self.list_of_deltas = []
|
||||
|
||||
|
||||
def record_input(self):
|
||||
if self.last_time == None:
|
||||
self.last_time = datetime.datetime.now()
|
||||
@@ -17,6 +18,6 @@ class FixedLengthSetter(object):
|
||||
self.list_of_deltas.append(now_time - self.last_time)
|
||||
self.last_time = now_time
|
||||
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)
|
||||
self.data.update_setting_value('sampler', 'FIXED_LENGTH', average_seconds)
|
||||
|
||||
@@ -9,6 +9,7 @@ class Plugin(object):
|
||||
"""Base class that each plugin must inherit from. within this class
|
||||
you must define the methods that all of your plugins must implement
|
||||
"""
|
||||
|
||||
@property
|
||||
def disabled(self):
|
||||
return type(self).__name__ not in self.pc.data.get_enabled_plugin_class_names()
|
||||
@@ -23,9 +24,11 @@ class Plugin(object):
|
||||
def start_plugin(self):
|
||||
print(">>Starting plugin " + type(self).__name__)
|
||||
|
||||
|
||||
class MidiFeedbackPlugin(Plugin):
|
||||
"""Base class for MIDI feedback plugins
|
||||
"""
|
||||
|
||||
def __init__(self, plugin_collection):
|
||||
super().__init__(plugin_collection)
|
||||
self.description = 'Outputs feedback about status to device eg MIDI pads'
|
||||
@@ -39,29 +42,32 @@ class MidiFeedbackPlugin(Plugin):
|
||||
def refresh_midi_feedback(self):
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class SequencePlugin(Plugin):
|
||||
"""Base class for plugins that run constantly or on demand for eg automation"""
|
||||
|
||||
def __init__(self, plugin_collection):
|
||||
super().__init__(plugin_collection)
|
||||
|
||||
@property
|
||||
def parserlist(self):
|
||||
return [
|
||||
( r"^run_automation$", self.run_automation ),
|
||||
( r"^stop_automation$", self.stop_automation ),
|
||||
( r"^toggle_pause_automation$", self.toggle_pause_automation ),
|
||||
( r"^pause_automation$", self.pause_automation ),
|
||||
( r"^toggle_loop_automation$", self.toggle_loop_automation ),
|
||||
( r"^set_automation_speed$", self.set_speed ),
|
||||
(r"^run_automation$", self.run_automation),
|
||||
(r"^stop_automation$", self.stop_automation),
|
||||
(r"^toggle_pause_automation$", self.toggle_pause_automation),
|
||||
(r"^pause_automation$", self.pause_automation),
|
||||
(r"^toggle_loop_automation$", self.toggle_loop_automation),
|
||||
(r"^set_automation_speed$", self.set_speed),
|
||||
]
|
||||
|
||||
def set_speed(self, speed):
|
||||
#self.speed = 2.0 * (2.0*(speed-0.5))
|
||||
speed = 2.0*(speed-0.5) # adjust to range -1 to +1
|
||||
negative = speed<0.0 # remember negative state cos we'll lose it in next
|
||||
# self.speed = 2.0 * (2.0*(speed-0.5))
|
||||
speed = 2.0 * (speed - 0.5) # adjust to range -1 to +1
|
||||
negative = speed < 0.0 # remember negative state cos we'll lose it in next
|
||||
self.speed = (speed * speed) * 2.0
|
||||
if negative: self.speed *= -1
|
||||
print ("automation speed is now %s" % self.speed)
|
||||
if negative:
|
||||
self.speed *= -1
|
||||
print("automation speed is now %s" % self.speed)
|
||||
|
||||
def toggle_automation(self):
|
||||
if not self.is_playing():
|
||||
@@ -81,26 +87,28 @@ class SequencePlugin(Plugin):
|
||||
def toggle_pause_automation(self):
|
||||
self.pause_flag = not self.is_paused()
|
||||
self.last_delta = -1
|
||||
#self.pause_flag = self.is_paused() and self.is_playing()
|
||||
if not self.is_paused() and self.is_playing(): #not 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():
|
||||
self.run_automation()
|
||||
|
||||
last_delta = -1
|
||||
last_delta = -1
|
||||
|
||||
def delta(self, now):
|
||||
if self.last_delta==-1:
|
||||
if self.last_delta == -1:
|
||||
self.last_delta = now
|
||||
r = now - self.last_delta
|
||||
self.last_delta = now
|
||||
return r
|
||||
|
||||
speed = 0.25 #1.0
|
||||
speed = 0.25 # 1.0
|
||||
|
||||
def move_delta(self, delta, speed):
|
||||
self.position += delta * speed
|
||||
if self.position>1.0:
|
||||
self.position = self.position-1.0
|
||||
if self.position > 1.0:
|
||||
self.position = self.position - 1.0
|
||||
self.iterations_count += 1
|
||||
elif self.position<0.0:
|
||||
self.position = self.position+1.0
|
||||
elif self.position < 0.0:
|
||||
self.position = self.position + 1.0
|
||||
self.iterations_count += 1
|
||||
|
||||
position = 0.0
|
||||
@@ -111,12 +119,13 @@ class SequencePlugin(Plugin):
|
||||
iterations_count = 0
|
||||
duration = 2000
|
||||
frequency = 100
|
||||
|
||||
def run_automation(self):
|
||||
import time
|
||||
|
||||
now = time.time()
|
||||
|
||||
#print("running automation at %s!" % self.position)
|
||||
# print("running automation at %s!" % self.position)
|
||||
if not self.is_paused():
|
||||
self.store_passed = None
|
||||
delta = self.delta(now)
|
||||
@@ -126,9 +135,9 @@ class SequencePlugin(Plugin):
|
||||
if not self.stop_flag and not self.disabled:
|
||||
self.pc.midi_input.root.after(self.frequency, self.run_automation)
|
||||
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.automation_start = None
|
||||
# self.automation_start = None
|
||||
self.iterations_count = 0
|
||||
|
||||
def is_paused(self):
|
||||
@@ -136,11 +145,12 @@ class SequencePlugin(Plugin):
|
||||
|
||||
def is_playing(self):
|
||||
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):
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class ActionsPlugin(Plugin):
|
||||
def __init__(self, plugin_collection):
|
||||
super().__init__(plugin_collection)
|
||||
@@ -148,7 +158,7 @@ class ActionsPlugin(Plugin):
|
||||
@property
|
||||
def parserlist(self):
|
||||
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
|
||||
@@ -158,7 +168,7 @@ class ActionsPlugin(Plugin):
|
||||
return True
|
||||
|
||||
for a in self.parserlist:
|
||||
if (a[0]==method_name):
|
||||
if (a[0] == method_name):
|
||||
return True
|
||||
regex = a[0]
|
||||
me = a[1]
|
||||
@@ -185,24 +195,28 @@ class ActionsPlugin(Plugin):
|
||||
|
||||
return (found_method, args)
|
||||
|
||||
|
||||
class DisplayPlugin(Plugin):
|
||||
"""Base class for plugins that want to show a user interface on the recur screen"""
|
||||
|
||||
def __init__(self, plugin_collection):
|
||||
super().__init__(plugin_collection)
|
||||
|
||||
def is_handled(self, name):
|
||||
raise NotImplementedError
|
||||
raise NotImplementedError
|
||||
|
||||
def get_display_modes(self):
|
||||
raise NotImplementedError
|
||||
raise NotImplementedError
|
||||
|
||||
def show_plugin(self, display):
|
||||
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))
|
||||
|
||||
|
||||
class ModulationReceiverPlugin(Plugin):
|
||||
"""Base class for plugins that want to be notified of a change to modulation values"""
|
||||
|
||||
def __init__(self, plugin_collection):
|
||||
super().__init__(plugin_collection)
|
||||
|
||||
@@ -210,8 +224,10 @@ class ModulationReceiverPlugin(Plugin):
|
||||
print("||||||set_modulation_value dummy!")
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class AutomationSourcePlugin(Plugin):
|
||||
"""Base class for plugins that offer things to save&playback to&from automation"""
|
||||
|
||||
@property
|
||||
def frame_key(self):
|
||||
return self.__class__.__name__
|
||||
@@ -226,7 +242,7 @@ class AutomationSourcePlugin(Plugin):
|
||||
raise NotImplementedError
|
||||
|
||||
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
|
||||
|
||||
# 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()
|
||||
|
||||
diff = {}
|
||||
for queue,message in cf.items():
|
||||
if lf.get(queue) is None or lf.get(queue)!=message:
|
||||
for queue, message in cf.items():
|
||||
if lf.get(queue) is None or lf.get(queue) != message:
|
||||
diff[queue] = message
|
||||
|
||||
#print (">>>>>> returning diff\n%s\n<<<<<" % diff)
|
||||
# print (">>>>>> returning diff\n%s\n<<<<<" % diff)
|
||||
return diff
|
||||
|
||||
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 = {}
|
||||
if data1 is None:
|
||||
output = data2.copy()
|
||||
else:
|
||||
output = data1.copy()
|
||||
output.update(data2)
|
||||
#print("merge_data returning\n\t%s" % output)
|
||||
#print("<<<<<<")
|
||||
# print("merge_data returning\n\t%s" % output)
|
||||
# print("<<<<<<")
|
||||
return output
|
||||
|
||||
def get_ignored_data(self, data, ignored):
|
||||
#frame = self.f
|
||||
f = data.copy() #frame.get(self.frame_key,{})
|
||||
for queue,item in f.items(): #frame.get(self.frame_key,{}).items():
|
||||
# frame = self.f
|
||||
f = data.copy() # frame.get(self.frame_key,{})
|
||||
for queue, item in f.items(): # frame.get(self.frame_key,{}).items():
|
||||
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
|
||||
return f
|
||||
|
||||
def is_frame_data_empty(self, data):
|
||||
if len(data)>0:
|
||||
if len(data) > 0:
|
||||
return False
|
||||
return True
|
||||
|
||||
@@ -281,6 +297,7 @@ class AutomationSourcePlugin(Plugin):
|
||||
|
||||
### TODO: experimental value interpolation -- doesn't work, and is slow!
|
||||
cmd_size = {}
|
||||
|
||||
def process_interpolate_clip(self, frames):
|
||||
# loop over every frame
|
||||
# for each property of each frame
|
||||
@@ -290,9 +307,9 @@ class AutomationSourcePlugin(Plugin):
|
||||
# else,
|
||||
# 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 = {}
|
||||
|
||||
"""for findex,frame in enumerate(frames):
|
||||
@@ -300,17 +317,17 @@ class AutomationSourcePlugin(Plugin):
|
||||
continue"""
|
||||
|
||||
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:
|
||||
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)
|
||||
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])
|
||||
if command is not None and command[1] is not None:
|
||||
last[queue] = command
|
||||
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 ] } ]
|
||||
bob = {}
|
||||
@@ -322,88 +339,88 @@ class AutomationSourcePlugin(Plugin):
|
||||
distance_cache[i-1] = bob"""
|
||||
|
||||
def process(self, findex, frame):
|
||||
#for queue,command in enumerate(frame.f.get(self.frame_key,[])):
|
||||
data = frame.f.get(self.frame_key,None)
|
||||
#if data is None:
|
||||
# for queue,command in enumerate(frame.f.get(self.frame_key,[])):
|
||||
data = frame.f.get(self.frame_key, None)
|
||||
# if data is None:
|
||||
# return
|
||||
for queue in queues:
|
||||
if last.get(queue) is not None:
|
||||
"""if data.get(queue) is not None:
|
||||
last[queue] = data.get(queue)
|
||||
continue"""
|
||||
for argindex,value in enumerate(last.get(queue)[1]):
|
||||
#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 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]
|
||||
continue
|
||||
gap,future_value = self.get_distance_value_command(frames,findex,queue,argindex)
|
||||
if gap==0 or future_value==value:
|
||||
continue
|
||||
#print("\tpassing %s and %s to interpolate" % (last[queue][argindex], future_value))
|
||||
newvalue = self.pc.fm.interpolate(last[queue][1][argindex], future_value, gap)
|
||||
if data is None:
|
||||
frame.f[self.frame_key] = {}
|
||||
data = frame.f[self.frame_key]
|
||||
if data.get(queue) is None:
|
||||
data[queue] = [last[queue][0], last[queue][1]]# [None]*self.cmd_size[queue]]
|
||||
#while len(data.get(queue)[1])<argindex:
|
||||
# data.get(queue)[1] += [] #.append(None)
|
||||
data.get(queue)[1][argindex] = int(newvalue)
|
||||
last[queue][1][argindex] = int(newvalue)
|
||||
"""if data.get(queue) is not None:
|
||||
last[queue] = data.get(queue)
|
||||
continue"""
|
||||
for argindex, value in enumerate(last.get(queue)[1]):
|
||||
# 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 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]
|
||||
continue
|
||||
gap, future_value = self.get_distance_value_command(frames, findex, queue, argindex)
|
||||
if gap == 0 or future_value == value:
|
||||
continue
|
||||
# print("\tpassing %s and %s to interpolate" % (last[queue][argindex], future_value))
|
||||
newvalue = self.pc.fm.interpolate(last[queue][1][argindex], future_value, gap)
|
||||
if data is None:
|
||||
frame.f[self.frame_key] = {}
|
||||
data = frame.f[self.frame_key]
|
||||
if data.get(queue) is None:
|
||||
data[queue] = [last[queue][0], last[queue][1]] # [None]*self.cmd_size[queue]]
|
||||
# while len(data.get(queue)[1])<argindex:
|
||||
# data.get(queue)[1] += [] #.append(None)
|
||||
data.get(queue)[1][argindex] = int(newvalue)
|
||||
last[queue][1][argindex] = int(newvalue)
|
||||
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)
|
||||
|
||||
for i in range(1):
|
||||
for findex,frame in enumerate(frames):
|
||||
if frame is None:
|
||||
continue
|
||||
for findex, frame in enumerate(frames):
|
||||
if frame is None:
|
||||
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 = {}
|
||||
|
||||
distance_cache = {}
|
||||
|
||||
def get_distance_value_command(self, frames, findex, queue, argindex):
|
||||
|
||||
distance_cache = self.distance_cache
|
||||
|
||||
# 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']
|
||||
#return len(frames)-
|
||||
return abs(position-findex), distance_cache.get(queue)[argindex]['value']
|
||||
# return len(frames)-
|
||||
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))
|
||||
for i in range(1,len(frames)):
|
||||
# print("\t\tget_distance_value_command(findex %s, queue %s, argindex %s)" %(findex,queue,argindex))
|
||||
for i in range(1, len(frames)):
|
||||
search_findex = i + findex
|
||||
search_findex %= len(frames)
|
||||
if frames[search_findex] is None:
|
||||
continue
|
||||
#print("\t\t\tgetting frame index %s" % search_findex)
|
||||
# print("\t\t\tgetting frame index %s" % search_findex)
|
||||
frame = frames[search_findex]
|
||||
data = frame.f.get(self.frame_key,None)
|
||||
#print("\t\t\tgot frame data %s" % data)
|
||||
data = frame.f.get(self.frame_key, None)
|
||||
# print("\t\t\tgot frame data %s" % data)
|
||||
if data is None:
|
||||
continue
|
||||
command = data.get(queue,None)
|
||||
command = data.get(queue, None)
|
||||
if command is None:
|
||||
continue
|
||||
print("\t\t\tget_distance_value_command testing %s argindex %s - command looks like %s" % (queue, argindex, command))
|
||||
if len(command[1])>argindex:
|
||||
if command[1][argindex] is not None and findex!=i:
|
||||
if len(command[1]) > argindex:
|
||||
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]))
|
||||
if distance_cache.get(queue) is None:
|
||||
distance_cache[queue] = [None]*(self.cmd_size[queue])
|
||||
#while len(distance_cache[queue])<(argindex+1):
|
||||
distance_cache[queue] = [None] * (self.cmd_size[queue])
|
||||
# while len(distance_cache[queue])<(argindex+1):
|
||||
# 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]
|
||||
|
||||
|
||||
"""if frames[search_findex] is not None and frames[search_findex].f.get(self.frame_key,{}).get(queue,[])[argindex] is not None:
|
||||
return i, frames[search_findex].f.get(self.frame_key,{}).get(queue,[])[argindex]"""
|
||||
return 0, None
|
||||
@@ -416,6 +433,7 @@ class PluginCollection(object):
|
||||
"""Upon creation, this class will read the plugins package for modules
|
||||
that contain a class definition that is inheriting from the Plugin class
|
||||
"""
|
||||
|
||||
@property
|
||||
def display(self):
|
||||
return self.actions.display
|
||||
@@ -438,9 +456,9 @@ class PluginCollection(object):
|
||||
"""
|
||||
self.plugin_package = plugin_package
|
||||
self.message_handler = message_handler
|
||||
#self.shaders = lambda: data.shaders
|
||||
# self.shaders = lambda: data.shaders
|
||||
self.data = data
|
||||
#self.actions = message_handler.actions
|
||||
# self.actions = message_handler.actions
|
||||
self.reload_plugins()
|
||||
|
||||
# set up a FrameManager too so that plugins can use it
|
||||
@@ -448,6 +466,7 @@ class PluginCollection(object):
|
||||
|
||||
def read_json(self, file_name):
|
||||
return self.data._read_plugin_json(file_name)
|
||||
|
||||
def update_json(self, file_name, data):
|
||||
return self.data._update_plugin_json(file_name, data)
|
||||
|
||||
@@ -464,7 +483,8 @@ class PluginCollection(object):
|
||||
def quit_plugins(self):
|
||||
# tell each plugin to quit
|
||||
for plugin in self.get_plugins():
|
||||
if not plugin.disabled: plugin.stop_plugin()
|
||||
if not plugin.disabled:
|
||||
plugin.stop_plugin()
|
||||
|
||||
def stop_plugin_name(self, name):
|
||||
for plugin in self.get_plugins(include_disabled=True):
|
||||
@@ -472,15 +492,14 @@ class PluginCollection(object):
|
||||
plugin.stop_plugin()
|
||||
|
||||
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):
|
||||
#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:
|
||||
#print("starting %s" %name)
|
||||
# print("starting %s" %name)
|
||||
plugin.start_plugin()
|
||||
|
||||
|
||||
def get_plugins(self, clazz = None, include_disabled = False):
|
||||
def get_plugins(self, clazz=None, include_disabled=False):
|
||||
if clazz:
|
||||
return [c for c in self.plugins if isinstance(c, clazz) and (include_disabled or not c.disabled)]
|
||||
else:
|
||||
@@ -488,8 +507,8 @@ class PluginCollection(object):
|
||||
|
||||
def get_plugin_for_class_name(self, class_name):
|
||||
for plugin in self.get_plugins():
|
||||
#print("got class name %s" % type(plugin).__name__==class_name)
|
||||
if type(plugin).__name__==class_name == class_name:
|
||||
# print("got class name %s" % type(plugin).__name__==class_name)
|
||||
if type(plugin).__name__ == class_name == class_name:
|
||||
return plugin
|
||||
return None
|
||||
|
||||
@@ -505,12 +524,11 @@ class PluginCollection(object):
|
||||
for (_, c) in clsmembers:
|
||||
# Only add classes that are a sub class of Plugin, but NOT Plugin itself
|
||||
# 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):
|
||||
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))
|
||||
|
||||
|
||||
# Now that we have looked at all the modules in the current package, start looking
|
||||
# recursively for additional modules in sub packages
|
||||
# disabled 03-2020 to try and avoid problem with subclasses-of-subclasses being listed twice..
|
||||
@@ -532,7 +550,6 @@ class PluginCollection(object):
|
||||
for child_pkg in child_pkgs:
|
||||
self.walk_package(package + '.' + child_pkg)"""
|
||||
|
||||
|
||||
## helpers
|
||||
def get_variable(self, varname, default=0.0):
|
||||
from plugins.ManipulatePlugin import ManipulatePlugin
|
||||
|
||||
@@ -9,7 +9,7 @@ class Display(object):
|
||||
MENU_HEIGHT = 10
|
||||
SELECTOR_WIDTH = 0.47
|
||||
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):
|
||||
self.tk = tk
|
||||
@@ -18,7 +18,7 @@ class Display(object):
|
||||
self.shaders = shaders
|
||||
self.message_handler = message_handler
|
||||
self.data = data
|
||||
self.browser_menu = menu.BrowserMenu(self.data, self.message_handler, self.MENU_HEIGHT)
|
||||
self.browser_menu = menu.BrowserMenu(self.data, self.message_handler, self.MENU_HEIGHT)
|
||||
self.settings_menu = menu.SettingsMenu(self.data, self.message_handler, self.MENU_HEIGHT)
|
||||
self.plugins_menu = menu.PluginsMenu(self.data, self.message_handler, self.MENU_HEIGHT)
|
||||
self.shaders_menu = self.shaders.shaders_menu
|
||||
@@ -45,13 +45,13 @@ class Display(object):
|
||||
self.display_text.tag_configure("FUNCTION", background="yellow", foreground="black")
|
||||
self.display_text.tag_configure("BROKEN_PATH", background="black", foreground="gray")
|
||||
self.display_text.tag_configure("ZEBRA_STRIPE", background="black", foreground="khaki")
|
||||
|
||||
|
||||
def _load_display(self):
|
||||
self._load_title()
|
||||
self._load_player()
|
||||
self._load_display_body()
|
||||
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()
|
||||
|
||||
def _load_title(self):
|
||||
@@ -79,7 +79,7 @@ class Display(object):
|
||||
self.display_text.insert(END, status + '\n')
|
||||
self.display_text.tag_add("NOW_ALPHA", 3.0, 3.17)
|
||||
self.display_text.tag_add("CAPTURE_ALPHA", 3.18, 3.29)
|
||||
self.display_text.tag_add("NEXT_ALPHA", 3.29, 3.47)
|
||||
self.display_text.tag_add("NEXT_ALPHA", 3.29, 3.47)
|
||||
|
||||
def _load_display_body(self):
|
||||
self.body_title = self._generate_body_title()
|
||||
@@ -106,35 +106,34 @@ class Display(object):
|
||||
self._load_plugin_page(self.data.display_mode, plugin)
|
||||
self.display_text.tag_add("DISPLAY_MODE", 4.19, 4.29)
|
||||
self.display_text.tag_add("COLUMN_NAME", 5.0, 6.0)
|
||||
|
||||
|
||||
def _load_plugin_page(self, display_mode, plugin):
|
||||
plugin.show_plugin(self, display_mode)
|
||||
|
||||
def _load_sampler(self):
|
||||
bank_data = self.data.bank_data[self.data.bank_number]
|
||||
|
||||
|
||||
self.display_text.insert(END, '{} \n'.format(self.body_title))
|
||||
|
||||
|
||||
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):
|
||||
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(
|
||||
index, name_without_extension[0:17], self.format_time_value(slot['length']),
|
||||
self.format_time_value(slot['start']), self.format_time_value(slot['end'])))
|
||||
index, name_without_extension[0:17], self.format_time_value(slot['length']),
|
||||
self.format_time_value(slot['start']), self.format_time_value(slot['end'])))
|
||||
if index % 2:
|
||||
self.display_text.tag_add("ZEBRA_STRIPE", self.ROW_OFFSET + index,
|
||||
self.ROW_OFFSET + self.SELECTOR_WIDTH + index)
|
||||
self.ROW_OFFSET + self.SELECTOR_WIDTH + index)
|
||||
if self.data.is_this_path_broken(slot['location']):
|
||||
self.display_text.tag_add("BROKEN_PATH", self.ROW_OFFSET + index,
|
||||
self.ROW_OFFSET + self.SELECTOR_WIDTH + index)
|
||||
self.ROW_OFFSET + self.SELECTOR_WIDTH + index)
|
||||
# highlight the slot of the selected player
|
||||
if self.data.player_mode == 'next':
|
||||
bank_slot = self.video_driver.next_player.bankslot_number
|
||||
bank_slot = self.video_driver.next_player.bankslot_number
|
||||
else:
|
||||
bank_slot = self.video_driver.current_player.bankslot_number
|
||||
current_bank , current_slot = self.data.split_bankslot_number(bank_slot)
|
||||
bank_slot = self.video_driver.current_player.bankslot_number
|
||||
current_bank, current_slot = self.data.split_bankslot_number(bank_slot)
|
||||
if current_bank is self.data.bank_number:
|
||||
self._highlight_this_row(current_slot)
|
||||
|
||||
@@ -142,7 +141,7 @@ class Display(object):
|
||||
browser_list = self.browser_menu.menu_list
|
||||
number_of_lines_displayed = 0
|
||||
self.display_text.insert(END, '{} \n'.format(self.body_title))
|
||||
|
||||
|
||||
self.display_text.insert(END, '{:40} {:5} \n'.format('path', 'slot'))
|
||||
|
||||
number_of_browser_items = len(browser_list)
|
||||
@@ -163,7 +162,7 @@ class Display(object):
|
||||
line_count = 0
|
||||
settings_list = self.settings_menu.menu_list
|
||||
self.display_text.insert(END, '{} \n'.format(self.body_title))
|
||||
|
||||
|
||||
self.display_text.insert(END, '{:^23} {:^22} \n'.format('SETTING', 'VALUE'))
|
||||
number_of_settings_items = len(settings_list)
|
||||
for index in range(number_of_settings_items):
|
||||
@@ -182,17 +181,17 @@ class Display(object):
|
||||
def _load_plugins(self):
|
||||
line_count = 0
|
||||
self.display_text.insert(END, '{} \n'.format(self.body_title))
|
||||
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:
|
||||
plugins_list = sorted([
|
||||
(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)
|
||||
plugins_list = sorted([
|
||||
(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)
|
||||
])
|
||||
self.plugins_menu.menu_list = plugins_list
|
||||
|
||||
number_of_plugins = len(plugins_list)
|
||||
for index in range(number_of_plugins):
|
||||
if line_count >= self.MENU_HEIGHT :
|
||||
if line_count >= self.MENU_HEIGHT:
|
||||
break
|
||||
if index >= self.plugins_menu.top_menu_index:
|
||||
plugin_line = plugins_list[index]
|
||||
@@ -200,34 +199,33 @@ class Display(object):
|
||||
line_count = line_count + 1
|
||||
|
||||
for index in range(self.plugins_menu.top_menu_index + self.plugins_menu.menu_height - number_of_plugins):
|
||||
self.display_text.insert(END, '\n')
|
||||
self.display_text.insert(END, '\n')
|
||||
|
||||
self._highlight_this_row(self.plugins_menu.selected_list_index - self.plugins_menu.top_menu_index)
|
||||
|
||||
|
||||
def _load_shaders(self):
|
||||
line_count = 0
|
||||
self.display_text.insert(END, '{} \n'.format(self.body_title))
|
||||
|
||||
|
||||
## showing current shader info:
|
||||
shader = self.shaders.selected_shader_list[self.data.shader_layer]
|
||||
self.display_text.insert(END, '{:<1}{}{:<1}:{:<2} {:<16} '.format \
|
||||
(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],
|
||||
shader['name'].lstrip()[0:16] ))
|
||||
for i in range(min(4,shader['param_number'])):
|
||||
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],
|
||||
shader['name'].lstrip()[0:16]))
|
||||
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])
|
||||
if display_param == 100:
|
||||
display_param == 99
|
||||
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)
|
||||
## showing list of other shaders:
|
||||
shaders_list = self.shaders.shaders_menu_list
|
||||
number_of_shader_items = len(shaders_list)
|
||||
for index in range(number_of_shader_items):
|
||||
if line_count >= self.MENU_HEIGHT :
|
||||
if line_count >= self.MENU_HEIGHT:
|
||||
break
|
||||
if index >= self.shaders.shaders_menu.top_menu_index:
|
||||
shader_line = shaders_list[index]
|
||||
@@ -235,7 +233,7 @@ class Display(object):
|
||||
line_count = line_count + 1
|
||||
|
||||
for index in range(self.shaders.shaders_menu.top_menu_index + self.shaders.shaders_menu.menu_height - number_of_shader_items):
|
||||
self.display_text.insert(END, '\n')
|
||||
self.display_text.insert(END, '\n')
|
||||
|
||||
self._highlight_this_row(self.shaders.shaders_menu.selected_list_index - self.shaders.shaders_menu.top_menu_index)
|
||||
if self.data.control_mode == "SHADER_PARAM":
|
||||
@@ -243,16 +241,16 @@ class Display(object):
|
||||
|
||||
def _load_shader_bank(self):
|
||||
shader_bank_data = self.data.shader_bank_data[self.data.shader_layer]
|
||||
|
||||
|
||||
self.display_text.insert(END, '{} \n'.format(self.body_title))
|
||||
|
||||
self.display_text.insert(END, '{:>6} {:<11} {:<5} '.format(
|
||||
'{} {}'.format(self.data.shader_layer, self.get_speed_indicator(self.shaders.selected_speed_list[self.data.shader_layer])),
|
||||
'name', 'type'))
|
||||
|
||||
'{} {}'.format(self.data.shader_layer, self.get_speed_indicator(self.shaders.selected_speed_list[self.data.shader_layer])),
|
||||
'name', 'type'))
|
||||
|
||||
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])
|
||||
if display_param == 100:
|
||||
display_param == 99
|
||||
@@ -260,11 +258,11 @@ class Display(object):
|
||||
self.display_text.insert(END, '\n')
|
||||
|
||||
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']))
|
||||
if index % 2:
|
||||
self.display_text.tag_add("ZEBRA_STRIPE", self.ROW_OFFSET + index,
|
||||
self.ROW_OFFSET + self.SELECTOR_WIDTH + index)
|
||||
self.ROW_OFFSET + self.SELECTOR_WIDTH + index)
|
||||
# highlight the slot of the selected player
|
||||
current_slot = self.shaders.selected_shader_list[self.data.shader_layer].get('slot', None)
|
||||
not_playing_tag = self.shaders.selected_status_list[self.data.shader_layer] != '▶'
|
||||
@@ -275,15 +273,15 @@ class Display(object):
|
||||
|
||||
def _load_modulation_bank(self):
|
||||
shader_bank_data = self.data.shader_bank_data[self.data.shader_layer]
|
||||
|
||||
|
||||
self.display_text.insert(END, '{} \n'.format(self.body_title))
|
||||
|
||||
self.display_text.insert(END, '{:>6} {:<11} {:<5} '.format(
|
||||
'{} {}'.format(self.data.shader_layer, self.get_speed_indicator(self.shaders.selected_speed_list[self.data.shader_layer])),
|
||||
'name', 'type'))
|
||||
'{} {}'.format(self.data.shader_layer, self.get_speed_indicator(self.shaders.selected_speed_list[self.data.shader_layer])),
|
||||
'name', 'type'))
|
||||
|
||||
shader = self.shaders.selected_shader_list[self.data.shader_layer]
|
||||
|
||||
|
||||
"""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])
|
||||
if display_param == 100:
|
||||
@@ -314,8 +312,8 @@ class Display(object):
|
||||
self._highlight_this_param(self.shaders.focused_param) """
|
||||
|
||||
# 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")
|
||||
# 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")
|
||||
"""for i in range(4):
|
||||
self.display_text.insert(END, "|%s"%i)
|
||||
for i in range(4):
|
||||
@@ -323,7 +321,7 @@ class Display(object):
|
||||
if i==self.shaders.selected_modulation_slot:
|
||||
a = a.upper()
|
||||
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):
|
||||
if (layer==self.data.shader_layer):
|
||||
self.display_text.insert(END, '*')
|
||||
@@ -343,14 +341,14 @@ class Display(object):
|
||||
o += "\n Modmatrix:\t"
|
||||
|
||||
name = self.shaders.selected_shader_list[layer].get('name').strip()
|
||||
#o = ""
|
||||
# o = ""
|
||||
for slot in range(4):
|
||||
sl = self.get_mod_slot_label(slot)
|
||||
o+= sl + ("[" if sl.isupper() else "-")
|
||||
o += sl + ("[" if sl.isupper() else "-")
|
||||
for param in range(4):
|
||||
o += self.get_bar(self.shaders.modulation_level[layer][param][slot])
|
||||
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))
|
||||
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, '\n')
|
||||
# todo: this doesnt work but would be a better way to highlight the selected modulation slot/layer
|
||||
"""self._highlight_this_param(
|
||||
@@ -360,12 +358,11 @@ class Display(object):
|
||||
column_offset = 0.1
|
||||
)"""
|
||||
|
||||
|
||||
def _load_detour(self):
|
||||
line_count = 0
|
||||
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("DETOUR_ACTIVE", self.data.detour_active))
|
||||
for index, (key, value) in enumerate(self.data.detour_settings.items()):
|
||||
@@ -379,30 +376,30 @@ class Display(object):
|
||||
def _load_message(self):
|
||||
if self.message_handler.current_message[1]:
|
||||
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.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]:
|
||||
self.message_handler.current_message[2] = False
|
||||
message_length = 4000
|
||||
self.tk.after(message_length, self.message_handler.clear_message)
|
||||
elif self.data.function_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:
|
||||
feedback = ''
|
||||
if self.data.feedback_active:
|
||||
feedback = 'FDBCK'
|
||||
|
||||
|
||||
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):
|
||||
highlight_tag = "SELECT"
|
||||
if gray:
|
||||
highlight_tag = "BROKEN_PATH"
|
||||
highlight_tag = "BROKEN_PATH"
|
||||
self.display_text.tag_remove("ZEBRA_STRIPE", self.ROW_OFFSET + row,
|
||||
self.ROW_OFFSET + self.SELECTOR_WIDTH + row)
|
||||
self.ROW_OFFSET + self.SELECTOR_WIDTH + row)
|
||||
self.display_text.tag_add(highlight_tag, self.ROW_OFFSET + row,
|
||||
self.ROW_OFFSET + self.SELECTOR_WIDTH + row)
|
||||
|
||||
@@ -410,13 +407,13 @@ class Display(object):
|
||||
self.display_text.tag_remove("SELECT", self.ROW_OFFSET + 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:
|
||||
param_row = self.ROW_OFFSET - 1
|
||||
self.display_text.tag_add("SHADER_PARAM",
|
||||
round(param_row + column_offset + param_num*param_length,2),
|
||||
round(param_row + column_offset + (param_num+1)*param_length, 2)
|
||||
)
|
||||
self.display_text.tag_add("SHADER_PARAM",
|
||||
round(param_row + column_offset + param_num * param_length, 2),
|
||||
round(param_row + column_offset + (param_num + 1) * param_length, 2)
|
||||
)
|
||||
|
||||
def _get_status_for_player(self):
|
||||
now_slot, now_status, now_alpha, next_slot, next_status, next_alpha = self.video_driver.get_player_info_for_status()
|
||||
@@ -427,20 +424,19 @@ class Display(object):
|
||||
else:
|
||||
capture_status = ''
|
||||
preview_alpha = 0
|
||||
|
||||
|
||||
if preview_alpha == None:
|
||||
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)
|
||||
|
||||
now_info = 'NOW [{}] {}'.format(now_slot, now_status)
|
||||
next_info = 'NEXT [{}] {}'.format(next_slot, next_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)
|
||||
banner = self.create_video_display_banner(start, end, position)
|
||||
time_been = self.format_time_value(position - start)
|
||||
@@ -448,35 +444,37 @@ class Display(object):
|
||||
return ' {:5} {} {:5}'.format(time_been, banner, time_left)
|
||||
|
||||
def _generate_capture_status(self):
|
||||
is_previewing = self.capture.is_previewing
|
||||
is_previewing = self.capture.is_previewing
|
||||
is_recording = self.capture.is_recording
|
||||
rec_time = -1
|
||||
if is_recording == True:
|
||||
rec_time = self.capture.get_recording_time()
|
||||
capture_status = ''
|
||||
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':
|
||||
capture_status = '<{}>'.format('_saving_')
|
||||
elif is_previewing:
|
||||
capture_status = '<{}>'.format('_preview')
|
||||
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':
|
||||
capture_status = '[{}]'.format('_saving_')
|
||||
capture_status = '[{}]'.format('_saving_')
|
||||
else:
|
||||
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:
|
||||
return " "
|
||||
value = abs(value / max_value) # abs() so negative values make some sense
|
||||
if value>1.0: value = 1.0
|
||||
elif value<0.0: value = 0.0
|
||||
value = abs(value / max_value) # abs() so negative values make some sense
|
||||
if value > 1.0:
|
||||
value = 1.0
|
||||
elif value < 0.0:
|
||||
value = 0.0
|
||||
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
|
||||
|
||||
def get_mod_slot_label(self, slot):
|
||||
@@ -485,35 +483,35 @@ class Display(object):
|
||||
sl = sl.lower()
|
||||
return sl
|
||||
|
||||
def get_speed_indicator(self, value, convert = True):
|
||||
def get_speed_indicator(self, value, convert=True):
|
||||
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""
|
||||
if value==0.0 or (value>=-0.02 and value<=0.02):
|
||||
output+=u"\u23f9" # stopped
|
||||
elif value<=-0.5:
|
||||
output+=u"\u00AB" # fast reverse
|
||||
elif value<0.0:
|
||||
output+=u"\u2039" # reverse
|
||||
elif value>=0.5:
|
||||
output+=u"\u00BB" # fast forward
|
||||
elif value>0.0:
|
||||
output+=u"\u203A" # forward
|
||||
if value == 0.0 or (value >= -0.02 and value <= 0.02):
|
||||
output += u"\u23f9" # stopped
|
||||
elif value <= -0.5:
|
||||
output += u"\u00AB" # fast reverse
|
||||
elif value < 0.0:
|
||||
output += u"\u2039" # reverse
|
||||
elif value >= 0.5:
|
||||
output += u"\u00BB" # fast forward
|
||||
elif value > 0.0:
|
||||
output += u"\u203A" # forward
|
||||
|
||||
#output += " {:03f}".format(value)
|
||||
# output += " {:03f}".format(value)
|
||||
output += self.get_bar(value)
|
||||
|
||||
return output
|
||||
|
||||
def get_compact_indicators(self, inp):
|
||||
step = 2
|
||||
step = 2
|
||||
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]
|
||||
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
|
||||
else:
|
||||
selected2 = inp[i+1]
|
||||
selected2 = inp[i + 1]
|
||||
|
||||
if selected1 and selected2:
|
||||
# full block
|
||||
@@ -528,11 +526,9 @@ class Display(object):
|
||||
# empty
|
||||
s += "_"
|
||||
|
||||
#s += "#" if selected else "-"
|
||||
# s += "#" if selected else "-"
|
||||
return s
|
||||
|
||||
|
||||
|
||||
@staticmethod
|
||||
def create_video_display_banner(start, end, position):
|
||||
banner_list = ['[', '-', '-', '-', '-', '-', '-', '-', '-',
|
||||
@@ -545,8 +541,8 @@ class Display(object):
|
||||
banner_list[0] = '<'
|
||||
elif position > end:
|
||||
banner_list[max] = '>'
|
||||
elif end - start != 0 and not math.isnan(position) :
|
||||
#print('start value is {}, end value is {}, position is {}'.format(start, end, position))
|
||||
elif end - start != 0 and not math.isnan(position):
|
||||
# print('start value is {}, end value is {}, position is {}'.format(start, end, position))
|
||||
marker = int(math.floor(float(position - start) /
|
||||
float(end - start) * (max - 1)) + 1)
|
||||
banner_list[marker] = '*'
|
||||
@@ -564,18 +560,18 @@ class Display(object):
|
||||
max = len(banner_list) - 1
|
||||
if size == 0:
|
||||
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:
|
||||
start = int(math.floor(float(start) /
|
||||
float(size) * (max - 1)) + 1)
|
||||
float(size) * (max - 1)) + 1)
|
||||
banner_list[start] = '['
|
||||
if end > 0:
|
||||
end = int(math.floor(float(end) /
|
||||
float(size) * (max - 1)) + 1)
|
||||
float(size) * (max - 1)) + 1)
|
||||
banner_list[end] = ']'
|
||||
position = int(math.floor(float(position) /
|
||||
float(size) * (max - 1)) + 1)
|
||||
if 0 <= position and position < len(banner_list):
|
||||
float(size) * (max - 1)) + 1)
|
||||
if 0 <= position and position < len(banner_list):
|
||||
banner_list[position] = '*'
|
||||
|
||||
return ''.join(banner_list)
|
||||
@@ -591,43 +587,43 @@ class Display(object):
|
||||
else:
|
||||
is_recording = False
|
||||
### scale values
|
||||
scaled_now = int(( now_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_now = int((now_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)
|
||||
|
||||
### convert to hex
|
||||
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)
|
||||
### update the colours
|
||||
self.display_text.tag_configure("NOW_ALPHA", background="black", foreground=now_colour)
|
||||
self.display_text.tag_configure("CAPTURE_ALPHA", background="black", foreground=capture_colour)
|
||||
self.display_text.tag_configure("NEXT_ALPHA", background="black", foreground=next_colour)
|
||||
self.display_text.tag_configure("NEXT_ALPHA", background="black", foreground=next_colour)
|
||||
|
||||
def _generate_body_title(self):
|
||||
display_modes = self.data.get_display_modes_list()
|
||||
current_mode = self.data.display_mode
|
||||
selected_list = []
|
||||
for index, v in enumerate(display_modes):
|
||||
if v == current_mode:
|
||||
if v == current_mode:
|
||||
while len(v) < 8:
|
||||
v = v + '_'
|
||||
selected_list.append('[{}]'.format(v))
|
||||
selected_list_index = index
|
||||
else:
|
||||
selected_list.append('<{}>'.format(v[:2].lower()))
|
||||
# 18 char to PURPLE : 18 - 29 ,18 after
|
||||
if selected_list_index>4:
|
||||
selected_list = selected_list[selected_list_index-4:len(selected_list)]
|
||||
selected_list.append('<{}>'.format(v[:2].lower()))
|
||||
# 18 char to PURPLE : 18 - 29 ,18 after
|
||||
if selected_list_index > 4:
|
||||
selected_list = selected_list[selected_list_index - 4:len(selected_list)]
|
||||
selected_list = ['--'] + 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 = selected_string[:30]
|
||||
#wid = 19 #int(2+((len(display_modes)/2)*4))
|
||||
output = ('-' * ((19) - (selected_list_index * 4))) + \
|
||||
selected_string + \
|
||||
('-' * (18 - ((len(display_modes) - selected_list_index - 1) * 4)))
|
||||
# selected_string = selected_string[:30]
|
||||
# wid = 19 #int(2+((len(display_modes)/2)*4))
|
||||
output = ('-' * ((19) - (selected_list_index * 4))) + \
|
||||
selected_string + \
|
||||
('-' * (18 - ((len(display_modes) - selected_list_index - 1) * 4)))
|
||||
output = output[0:46]
|
||||
return output
|
||||
|
||||
@@ -641,11 +637,12 @@ class Display(object):
|
||||
|
||||
last_refreshed = 0
|
||||
REFRESH_LIMIT = 100
|
||||
|
||||
def refresh_display(self):
|
||||
if self.data.update_screen:
|
||||
if time.time()*1000 - self.last_refreshed < self.REFRESH_LIMIT:
|
||||
if time.time() * 1000 - self.last_refreshed < self.REFRESH_LIMIT:
|
||||
return
|
||||
self.last_refreshed = time.time()*1000
|
||||
self.last_refreshed = time.time() * 1000
|
||||
self.display_text.configure(state='normal')
|
||||
self.display_text.delete(1.0, END)
|
||||
self._load_display()
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
import os
|
||||
|
||||
|
||||
class Menu(object):
|
||||
def __init__(self, data, message_handler, menu_height):
|
||||
self.data = data
|
||||
self.message_handler = message_handler
|
||||
self.message_handler = message_handler
|
||||
self.open_folders = []
|
||||
self.menu_list = []
|
||||
self.menu_height = menu_height
|
||||
self.top_menu_index = 0
|
||||
|
||||
self.selected_list_index = 0
|
||||
|
||||
|
||||
def navigate_menu_up(self):
|
||||
if self.selected_list_index != 0:
|
||||
if self.selected_list_index == self.top_menu_index:
|
||||
@@ -27,7 +28,7 @@ class Menu(object):
|
||||
if self.top_menu_index < self.menu_height:
|
||||
self.top_menu_index = 0
|
||||
self.selected_list_index = 0
|
||||
else:
|
||||
else:
|
||||
self.top_menu_index -= self.menu_height
|
||||
self.selected_list_index -= self.menu_height
|
||||
print('self.top_menu_index ', self.top_menu_index)
|
||||
@@ -50,20 +51,19 @@ class Menu(object):
|
||||
self.top_menu_index += self.menu_height
|
||||
self.selected_list_index = min(self.menu_height + self.selected_list_index, len(self.menu_list) - 1)
|
||||
|
||||
|
||||
def update_open_folders(self, folder_name):
|
||||
if folder_name not in self.open_folders:
|
||||
self.open_folders.append(folder_name)
|
||||
else:
|
||||
self.open_folders.remove(folder_name)
|
||||
|
||||
|
||||
def _check_folder_state(self, folder_name):
|
||||
######## used for displaying folders as open or closed ########
|
||||
if folder_name in self.open_folders:
|
||||
return True, '/'
|
||||
else:
|
||||
return False, '|'
|
||||
|
||||
|
||||
@staticmethod
|
||||
def extract_file_type_and_name_from_menu_format(dir_name):
|
||||
# removes whitespace and folder state from display item ########
|
||||
@@ -72,7 +72,8 @@ class Menu(object):
|
||||
else:
|
||||
return True, dir_name.lstrip()
|
||||
|
||||
class BrowserMenu(Menu):
|
||||
|
||||
class BrowserMenu(Menu):
|
||||
def __init__(self, data, message_handler, menu_height):
|
||||
Menu.__init__(self, data, message_handler, menu_height)
|
||||
self.generate_browser_list()
|
||||
@@ -82,7 +83,7 @@ class BrowserMenu(Menu):
|
||||
self.menu_list = []
|
||||
for path in self.data.PATHS_TO_BROWSER:
|
||||
self._add_folder_to_browser_list(path, 0)
|
||||
|
||||
|
||||
for browser_line in self.menu_list:
|
||||
is_file, name = self.extract_file_type_and_name_from_menu_format(browser_line['name'])
|
||||
if is_file:
|
||||
@@ -116,13 +117,12 @@ class BrowserMenu(Menu):
|
||||
for slot_index, slot in enumerate(bank):
|
||||
print('&&&&&&&&&&&&', slot)
|
||||
if file_name == slot['name']:
|
||||
return True, '{}-{}'.format(bank_index,slot_index)
|
||||
return True, '{}-{}'.format(bank_index, slot_index)
|
||||
return False, ''
|
||||
|
||||
|
||||
def enter_on_browser_selection(self):
|
||||
is_file, name = self.extract_file_type_and_name_from_menu_format(
|
||||
self.menu_list[self.selected_list_index]['name'])
|
||||
self.menu_list[self.selected_list_index]['name'])
|
||||
if is_file:
|
||||
is_successful = self.data.create_new_slot_mapping_in_first_open(name)
|
||||
if not is_successful:
|
||||
@@ -133,17 +133,16 @@ class BrowserMenu(Menu):
|
||||
|
||||
|
||||
class SettingsMenu(Menu):
|
||||
|
||||
FOLDER_ORDER = ['video', 'sampler', 'user_input', 'capture', 'shader', 'detour', 'system' ]
|
||||
SAMPLER_ORDER = ['LOOP_TYPE', 'LOAD_NEXT', 'RAND_START_MODE', 'RESET_PLAYERS', 'FIXED_LENGTH_MODE', 'FIXED_LENGTH', 'FIXED_LENGTH_MULTIPLY' ]
|
||||
FOLDER_ORDER = ['video', 'sampler', 'user_input', 'capture', 'shader', 'detour', 'system']
|
||||
SAMPLER_ORDER = ['LOOP_TYPE', 'LOAD_NEXT', 'RAND_START_MODE', 'RESET_PLAYERS', 'FIXED_LENGTH_MODE', 'FIXED_LENGTH', 'FIXED_LENGTH_MULTIPLY']
|
||||
VIDEO_ORDER = ['VIDEOPLAYER_BACKEND']
|
||||
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']
|
||||
SHADER_ORDER = ['USER_SHADER']
|
||||
DETOUR_ORDER = ['TRY_DEMO']
|
||||
SYSTEM_ORDER = []
|
||||
|
||||
SETTINGS_TO_HIDE = ['OUTPUT' ]
|
||||
SETTINGS_TO_HIDE = ['OUTPUT']
|
||||
|
||||
def __init__(self, data, message_handler, menu_height):
|
||||
|
||||
@@ -159,16 +158,16 @@ class SettingsMenu(Menu):
|
||||
if setting_folder_key in self.open_folders:
|
||||
self.menu_list.append(dict(name='{}/'.format(setting_folder_key), value=''))
|
||||
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:
|
||||
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'])))
|
||||
else:
|
||||
else:
|
||||
self.menu_list.append(dict(name='{}|'.format(setting_folder_key), value=''))
|
||||
|
||||
def enter_on_setting_selection(self):
|
||||
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'])
|
||||
if is_file:
|
||||
folder, setting_name, setting_details = self.data.get_setting_and_folder_from_name(name)
|
||||
if setting_details['value'] in setting_details['options']:
|
||||
@@ -195,7 +194,7 @@ class SettingsMenu(Menu):
|
||||
for order_key in order_list:
|
||||
if order_key in dictionary:
|
||||
ordered_tuple_list.append((order_key, dictionary[order_key]))
|
||||
for other_key in sorted(dictionary):
|
||||
for other_key in sorted(dictionary):
|
||||
if other_key not in [i[0] for i in ordered_tuple_list]:
|
||||
ordered_tuple_list.append((other_key, dictionary[other_key]))
|
||||
return ordered_tuple_list
|
||||
@@ -219,8 +218,8 @@ class ShadersMenu(Menu):
|
||||
|
||||
def __init__(self, data, message_handler, menu_height):
|
||||
Menu.__init__(self, data, message_handler, menu_height)
|
||||
#self.top_menu_index = 1
|
||||
#self.selected_list_index = 1
|
||||
# self.top_menu_index = 1
|
||||
# self.selected_list_index = 1
|
||||
|
||||
def generate_raw_shaders_list(self):
|
||||
######## starts the recursive process of listing all folders and shader files to display ########
|
||||
@@ -228,11 +227,10 @@ class ShadersMenu(Menu):
|
||||
for path in self.data.PATHS_TO_SHADERS:
|
||||
self._add_folder_to_shaders_list(path, 0)
|
||||
return self.menu_list
|
||||
|
||||
|
||||
def _add_folder_to_shaders_list(self, current_path, current_level):
|
||||
######## adds the folders and shader files at the current level to the results list. recursively recalls at deeper level if folder is open ########
|
||||
|
||||
|
||||
root, dirs, files = next(os.walk(current_path))
|
||||
|
||||
indent = ' ' * 4 * (current_level)
|
||||
@@ -249,8 +247,3 @@ class ShadersMenu(Menu):
|
||||
split_name = os.path.splitext(f)
|
||||
if (split_name[1].lower() in ['.frag', '.shader', '.glsl', '.glslf', '.fsh']):
|
||||
self.menu_list.append(dict(name='{}{}'.format(indent, f), is_shader=True))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import logging
|
||||
|
||||
|
||||
class MessageHandler(object):
|
||||
def __init__(self):
|
||||
self.current_message = [None, None, None]
|
||||
|
||||
@@ -12,8 +12,9 @@ def setup_osc_client(ip, port):
|
||||
|
||||
return udp_client.SimpleUDPClient(client_args.ip, client_args.port)
|
||||
|
||||
client = setup_osc_client('127.0.0.1',5433)
|
||||
|
||||
client = setup_osc_client('127.0.0.1', 5433)
|
||||
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)
|
||||
|
||||
@@ -3,8 +3,7 @@ import math
|
||||
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
|
||||
|
||||
PRESET_FILE_NAME = "LFOModulationPlugin/config.json"
|
||||
@@ -16,7 +15,7 @@ class LFOModulationPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin, Automation
|
||||
selected_lfo = 0
|
||||
|
||||
# for keeping track of LFO levels
|
||||
level = [0.0]*MAX_LFOS
|
||||
level = [0.0] * MAX_LFOS
|
||||
speed = 0.5
|
||||
|
||||
# TODO: enable assigning of LFOs to mod slots
|
||||
@@ -26,17 +25,18 @@ class LFOModulationPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin, Automation
|
||||
|
||||
stop_flag = False
|
||||
pause_flag = False
|
||||
|
||||
def __init__(self, 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.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.set_lfo_speed_direct(self.presets.get('speed', self.speed))
|
||||
|
||||
self.pc.shaders.root.after(1000, self.start_plugin)
|
||||
|
||||
|
||||
def start_plugin(self):
|
||||
super().start_plugin()
|
||||
self.pc.shaders.root.after(0, self.run_automation)
|
||||
@@ -47,30 +47,30 @@ class LFOModulationPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin, Automation
|
||||
|
||||
def load_presets(self):
|
||||
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):
|
||||
#for cmd,struct in self.commands.items():
|
||||
# for cmd,struct in self.commands.items():
|
||||
# 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
|
||||
def get_display_modes(self):
|
||||
return ['LFOMODU','NAV_LFO']
|
||||
return ['LFOMODU', 'NAV_LFO']
|
||||
|
||||
def show_plugin(self, display, display_mode):
|
||||
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, "LFOModulation is ")
|
||||
|
||||
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):
|
||||
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)))
|
||||
for lfo, value in enumerate(self.level):
|
||||
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, "{}\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]))
|
||||
|
||||
@@ -80,9 +80,9 @@ class LFOModulationPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin, Automation
|
||||
# methods/vars for AutomationSourcePlugin
|
||||
# a lot of the nitty-gritty handled in parent class, these are for interfacing to the plugin
|
||||
def get_frame_data(self):
|
||||
diff = { 'levels': self.level.copy(), 'speed': self.speed, 'active': self.active }
|
||||
#self.last_record = {}
|
||||
#print(">>> reporting frame data for rec\n\t%s" % diff)
|
||||
diff = {'levels': self.level.copy(), 'speed': self.speed, 'active': self.active}
|
||||
# self.last_record = {}
|
||||
# print(">>> reporting frame data for rec\n\t%s" % diff)
|
||||
return diff
|
||||
|
||||
def recall_frame_data(self, data):
|
||||
@@ -90,7 +90,7 @@ class LFOModulationPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin, Automation
|
||||
return
|
||||
# print(">>>>recall from data:\n\t%s\n" %data)
|
||||
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)
|
||||
if data.get('active') is not None:
|
||||
self.active = data.get('active')
|
||||
@@ -108,41 +108,43 @@ class LFOModulationPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin, Automation
|
||||
line += "active " if data.get('active') else 'inactive '
|
||||
if data.get('speed') is not None:
|
||||
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
|
||||
|
||||
# ActionsPlugin methods
|
||||
@property
|
||||
def parserlist(self):
|
||||
return [
|
||||
( r"^set_lfo_modulation_([0-3])_level$", self.set_lfo_modulation_level ),
|
||||
( r"^toggle_lfo_active$", self.toggle_lfo_active ),
|
||||
( r"^set_lfo_speed", self.set_lfo_speed ),
|
||||
( r"^select_lfo$", self.select_lfo ),
|
||||
( r"^select_previous_lfo$", self.select_previous_lfo ),
|
||||
( r"^select_next_lfo$", self.select_next_lfo ),
|
||||
( r"^increase_lfo_([0-3])_level$", self.increase_lfo_level ),
|
||||
( r"^decrease_lfo_([0-3])_level$", self.decrease_lfo_level ),
|
||||
( r"^increase_selected_lfo_level$", self.increase_selected_lfo_level ),
|
||||
( r"^decrease_selected_lfo_level$", self.decrease_selected_lfo_level ),
|
||||
( r"^increase_lfo_speed", self.increase_lfo_speed ),
|
||||
( r"^decrease_lfo_speed", self.decrease_lfo_speed ),
|
||||
# TODO: changing formulas and LFO modes
|
||||
return [
|
||||
(r"^set_lfo_modulation_([0-3])_level$", self.set_lfo_modulation_level),
|
||||
(r"^toggle_lfo_active$", self.toggle_lfo_active),
|
||||
(r"^set_lfo_speed", self.set_lfo_speed),
|
||||
(r"^select_lfo$", self.select_lfo),
|
||||
(r"^select_previous_lfo$", self.select_previous_lfo),
|
||||
(r"^select_next_lfo$", self.select_next_lfo),
|
||||
(r"^increase_lfo_([0-3])_level$", self.increase_lfo_level),
|
||||
(r"^decrease_lfo_([0-3])_level$", self.decrease_lfo_level),
|
||||
(r"^increase_selected_lfo_level$", self.increase_selected_lfo_level),
|
||||
(r"^decrease_selected_lfo_level$", self.decrease_selected_lfo_level),
|
||||
(r"^increase_lfo_speed", self.increase_lfo_speed),
|
||||
(r"^decrease_lfo_speed", self.decrease_lfo_speed),
|
||||
# TODO: changing formulas and LFO modes
|
||||
]
|
||||
|
||||
def set_lfo_modulation_level(self, slot, value):
|
||||
if (value<0.0): value = 0.0
|
||||
if (value>1.0): value = 1.0
|
||||
if (value < 0.0):
|
||||
value = 0.0
|
||||
if (value > 1.0):
|
||||
value = 1.0
|
||||
self.level[slot] = value
|
||||
|
||||
def set_lfo_speed(self, speed):
|
||||
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):
|
||||
self.speed = speed
|
||||
if self.speed<-2.0:
|
||||
if self.speed < -2.0:
|
||||
self.speed = -2.0
|
||||
if self.speed>2.0:
|
||||
if self.speed > 2.0:
|
||||
self.speed = 2.0
|
||||
|
||||
def toggle_lfo_active(self):
|
||||
@@ -151,66 +153,73 @@ class LFOModulationPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin, Automation
|
||||
|
||||
def select_lfo(self, lfo):
|
||||
self.selected_lfo = lfo
|
||||
if self.selected_lfo>=self.MAX_LFOS:
|
||||
if self.selected_lfo >= self.MAX_LFOS:
|
||||
self.selected_lfo = 0
|
||||
if self.selected_lfo<0:
|
||||
self.selected_lfo = self.MAX_LFOS-1
|
||||
if self.selected_lfo < 0:
|
||||
self.selected_lfo = self.MAX_LFOS - 1
|
||||
|
||||
def select_next_lfo(self):
|
||||
self.select_lfo(self.selected_lfo+1)
|
||||
self.select_lfo(self.selected_lfo + 1)
|
||||
|
||||
def select_previous_lfo(self):
|
||||
self.select_lfo(self.selected_lfo-1)
|
||||
self.select_lfo(self.selected_lfo - 1)
|
||||
|
||||
level_step = 0.125
|
||||
|
||||
def increase_lfo_level(self, slot):
|
||||
self.set_lfo_modulation_level(slot, self.level[slot] + self.level_step)
|
||||
|
||||
def decrease_lfo_level(self, slot):
|
||||
self.set_lfo_modulation_level(slot, self.level[slot] - self.level_step)
|
||||
|
||||
def increase_selected_lfo_level(self):
|
||||
self.increase_lfo_level(self.selected_lfo)
|
||||
|
||||
def decrease_selected_lfo_level(self):
|
||||
self.decrease_lfo_level(self.selected_lfo)
|
||||
|
||||
lfo_step = 0.25
|
||||
|
||||
def increase_lfo_speed(self):
|
||||
self.set_lfo_speed_direct ( self.speed + self.lfo_step )
|
||||
if self.speed==0.0: # dont rest on 0 - set to a small amount forward
|
||||
self.set_lfo_speed_direct(self.speed + self.lfo_step)
|
||||
if self.speed == 0.0: # dont rest on 0 - set to a small amount forward
|
||||
self.speed = 0.05
|
||||
|
||||
def decrease_lfo_speed(self):
|
||||
self.set_lfo_speed_direct ( self.speed - self.lfo_step )
|
||||
if self.speed==0.0: # dont rest on 0 - set to a small amount forward
|
||||
self.set_lfo_speed_direct(self.speed - self.lfo_step)
|
||||
if self.speed == 0.0: # dont rest on 0 - set to a small amount forward
|
||||
self.speed = -0.05
|
||||
|
||||
# Formula handling for generating automation
|
||||
# mapping 0-3 to match the LFO
|
||||
# TODO: save & load this to config file, make editable
|
||||
formula = [
|
||||
"f_sin",
|
||||
"f_double_cos",
|
||||
"f_invert_sin",
|
||||
#"f_invert_double_cos",
|
||||
"f_linear"
|
||||
"f_sin",
|
||||
"f_double_cos",
|
||||
"f_invert_sin",
|
||||
# "f_invert_double_cos",
|
||||
"f_linear"
|
||||
]
|
||||
|
||||
# run the formula for the stored lfo configuration
|
||||
last_lfo_status = [None]*MAX_LFOS # for displaying status
|
||||
last_lfo_value = [None]*MAX_LFOS
|
||||
#lfo_speed = [1.0]*MAX_LFOS
|
||||
last_lfo_status = [None] * MAX_LFOS # for displaying status
|
||||
last_lfo_value = [None] * MAX_LFOS
|
||||
|
||||
# lfo_speed = [1.0]*MAX_LFOS
|
||||
def getLFO(self, position, lfo):
|
||||
lfo_value = getattr(self,self.formula[lfo])(position, self.level[lfo])
|
||||
lfo_value = getattr(self, self.formula[lfo])(position, self.level[lfo])
|
||||
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
|
||||
|
||||
# built-in waveshapes
|
||||
# outgoing values should be between 0 and 1!!
|
||||
# todo: more of the these, and better!
|
||||
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 *= level
|
||||
value += 0.5 # normalise to range 0 - 1
|
||||
value += 0.5 # normalise to range 0 - 1
|
||||
|
||||
return value
|
||||
|
||||
@@ -218,7 +227,7 @@ class LFOModulationPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin, Automation
|
||||
return 1.0 - self.f_sin(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):
|
||||
return 1.0 - self.f_double_cos(position, level)
|
||||
@@ -231,16 +240,16 @@ class LFOModulationPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin, Automation
|
||||
import time
|
||||
now = time.time()
|
||||
|
||||
if self.pc.data.plugins is None: # not initialised yet
|
||||
if self.pc.data.plugins is None: # not initialised yet
|
||||
return
|
||||
|
||||
if not self.active: # output is disabled
|
||||
if not self.active: # output is disabled
|
||||
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
|
||||
if self.level[lfo]>0.0:
|
||||
if self.level[lfo] > 0.0:
|
||||
self.pc.actions.call_method_name(
|
||||
"modulate_param_%s_to_amount_continuous"%lfo,
|
||||
"modulate_param_%s_to_amount_continuous" % lfo,
|
||||
self.getLFO(position, lfo)
|
||||
)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from data_centre.plugin_collection import ActionsPlugin, DisplayPlugin, ModulationReceiverPlugin#, SequencePlugin
|
||||
#import math
|
||||
from data_centre.plugin_collection import ActionsPlugin, DisplayPlugin, ModulationReceiverPlugin # , SequencePlugin
|
||||
|
||||
# import math
|
||||
|
||||
"""
|
||||
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
|
||||
|
||||
def __init__(self, plugin_collection):
|
||||
@@ -49,31 +50,32 @@ class ManipulatePlugin(ActionsPlugin,DisplayPlugin,ModulationReceiverPlugin):
|
||||
# ActionsPlugin methods
|
||||
@property
|
||||
def parserlist(self):
|
||||
return [
|
||||
( r"(.*)&&(.*)", self.run_multi ), # split && first since they need to be processed separately
|
||||
( r"^invert\|(.*)$", self.invert ),
|
||||
( r"^f:(.*):\|(.*)$", self.formula ), # formula eg ```f:sin(x):|```
|
||||
( 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"^(.*)>\&(.*)$", self.run_multi ), # pick up piped commands that duplicate a chain of values last
|
||||
return [
|
||||
(r"(.*)&&(.*)", self.run_multi), # split && first since they need to be processed separately
|
||||
(r"^invert\|(.*)$", self.invert),
|
||||
(r"^f:(.*):\|(.*)$", self.formula), # formula eg ```f:sin(x):|```
|
||||
(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"^(.*)>\&(.*)$", self.run_multi), # pick up piped commands that duplicate a chain of values last
|
||||
]
|
||||
|
||||
# DisplayPlugin methods
|
||||
def show_plugin(self, display, display_mode):
|
||||
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, "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))
|
||||
|
||||
def get_display_modes(self):
|
||||
return ["MANIPULA","NAV_MANI"] #"NAV_MANIPULATE"]
|
||||
return ["MANIPULA", "NAV_MANI"] # "NAV_MANIPULATE"]
|
||||
|
||||
# Actions
|
||||
def run_multi(self, action1, action2, value):
|
||||
if self.DEBUG: print("ManipulatePlugin>> multi-running '%s' and '%s' with value %s" % (action1, action2, value))
|
||||
if self.DEBUG:
|
||||
print("ManipulatePlugin>> multi-running '%s' and '%s' with value %s" % (action1, action2, value))
|
||||
self.pc.actions.call_method_name(action1, value)
|
||||
self.pc.actions.call_method_name(action2, value)
|
||||
|
||||
@@ -89,16 +91,19 @@ class ManipulatePlugin(ActionsPlugin,DisplayPlugin,ModulationReceiverPlugin):
|
||||
|
||||
def formula(self, formula, action, value):
|
||||
self.variables['x'] = value
|
||||
if self.DEBUG: print("ManipulatePlugin>> evaluating formula `%s` with value `%s`" % (formula, value))
|
||||
if self.DEBUG:
|
||||
print("ManipulatePlugin>> evaluating formula `%s` with value `%s`" % (formula, value))
|
||||
value = eval(formula, globals(), self.variables)
|
||||
if self.DEBUG: print("ManipulatePlugin>> got evaluated value `%s`" % value)
|
||||
if self.DEBUG:
|
||||
print("ManipulatePlugin>> got evaluated value `%s`" % value)
|
||||
|
||||
self.pc.actions.call_method_name(
|
||||
action, value
|
||||
)
|
||||
|
||||
def set_variable(self, var_name, value):
|
||||
if self.DEBUG: print("ManipulatePlugin>> set_variable (%s) to %s" % (var_name, value))
|
||||
if self.DEBUG:
|
||||
print("ManipulatePlugin>> set_variable (%s) to %s" % (var_name, value))
|
||||
self.variables[var_name] = value
|
||||
|
||||
def get_variable(self, var_name, default):
|
||||
@@ -108,16 +113,16 @@ class ManipulatePlugin(ActionsPlugin,DisplayPlugin,ModulationReceiverPlugin):
|
||||
return default
|
||||
|
||||
def recall_variable(self, var_name, action, *args):
|
||||
if self.DEBUG: print ("ManipulatePlugin>> recall_variable (%s) as %s" % (var_name,args))
|
||||
if self.DEBUG:
|
||||
print("ManipulatePlugin>> recall_variable (%s) as %s" % (var_name, args))
|
||||
self.pc.actions.call_method_name(
|
||||
action, self.variables.get(var_name)# + list(args)
|
||||
action, self.variables.get(var_name) # + list(args)
|
||||
)
|
||||
|
||||
|
||||
# ModulationReceiverPlugin methods
|
||||
# methods for ModulationReceiverPlugin - receives changes to the in-built modulation levels (-1 to +1)
|
||||
def set_modulation_value(self, param, value):
|
||||
# take modulation value and throw it to local parameter
|
||||
if self.DEBUG: print("||||| ManipulatePlugin received set_modulation_value for param %s with value %s!" % (param, value))
|
||||
if self.DEBUG:
|
||||
print("||||| ManipulatePlugin received set_modulation_value for param %s with value %s!" % (param, value))
|
||||
self.set_variable("MODVALUE%s" % ('ABCD'[param]), value)
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ from data_centre.plugin_collection import MidiFeedbackPlugin
|
||||
|
||||
|
||||
class MidiFeedbackAPCKey25Plugin(MidiFeedbackPlugin):
|
||||
#disabled = False
|
||||
# disabled = False
|
||||
|
||||
status = {}
|
||||
|
||||
@@ -12,12 +12,12 @@ class MidiFeedbackAPCKey25Plugin(MidiFeedbackPlugin):
|
||||
super().__init__(plugin_collection)
|
||||
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)
|
||||
if bind is not None and 'note_on' in bind:
|
||||
return int(bind.split(' ')[1])
|
||||
else:
|
||||
print ("bind is %s, returning default" % bind)
|
||||
print("bind is %s, returning default" % bind)
|
||||
return default
|
||||
|
||||
def stop_plugin(self):
|
||||
@@ -33,16 +33,16 @@ class MidiFeedbackAPCKey25Plugin(MidiFeedbackPlugin):
|
||||
self.init_notes()
|
||||
|
||||
def init_notes(self):
|
||||
self.NOTE_PLAY_SHADER = self.get_note('play_shader_0_0',32)
|
||||
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_PLAY_SHADER = self.get_note('play_shader_0_0', 32)
|
||||
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_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_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_LAYER_ON = [ #82, 83, 84
|
||||
self.get_note('toggle_shader_layer_%i'%i, 82+i) for i in range(0,3)
|
||||
]
|
||||
self.NOTE_SHADER_LAYER_ON = [ # 82, 83, 84
|
||||
self.get_note('toggle_shader_layer_%i' % i, 82 + i) for i in range(0, 3)
|
||||
]
|
||||
|
||||
def supports_midi_feedback(self, device_name):
|
||||
supported_devices = ['APC Key 25']
|
||||
@@ -52,16 +52,16 @@ class MidiFeedbackAPCKey25Plugin(MidiFeedbackPlugin):
|
||||
|
||||
def set_status(self, command='note_on', note=None, velocity=None):
|
||||
self.status[note] = {
|
||||
'command': command,
|
||||
'note': note,
|
||||
'velocity': velocity
|
||||
'command': command,
|
||||
'note': note,
|
||||
'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):
|
||||
#print("send_command(%s, %s)" % (note, velocity))
|
||||
# print("send_command(%s, %s)" % (note, velocity))
|
||||
self.midi_feedback_device.send(
|
||||
mido.Message(command, note=note, velocity=velocity)
|
||||
mido.Message(command, note=note, velocity=velocity)
|
||||
)
|
||||
|
||||
def feedback_shader_feedback(self, on):
|
||||
@@ -71,15 +71,16 @@ class MidiFeedbackAPCKey25Plugin(MidiFeedbackPlugin):
|
||||
self.set_status(note=self.NOTE_CAPTURE_PREVIEW, velocity=int(on))
|
||||
|
||||
def feedback_shader_on(self, layer, slot, colour=None):
|
||||
if colour is None: colour = self.COLOUR_GREEN
|
||||
self.set_status(note=(self.NOTE_PLAY_SHADER-(layer)*8)+slot, velocity=int(colour))
|
||||
if colour is None:
|
||||
colour = self.COLOUR_GREEN
|
||||
self.set_status(note=(self.NOTE_PLAY_SHADER - (layer) * 8) + slot, velocity=int(colour))
|
||||
|
||||
def feedback_shader_off(self, layer, slot):
|
||||
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):
|
||||
self.set_status(note=self.NOTE_SHADER_LAYER_ON[layer], velocity=self.COLOUR_GREEN)
|
||||
|
||||
|
||||
def feedback_shader_layer_off(self, layer):
|
||||
self.set_status(note=self.NOTE_SHADER_LAYER_ON[layer], velocity=self.COLOUR_OFF)
|
||||
|
||||
@@ -87,90 +88,90 @@ class MidiFeedbackAPCKey25Plugin(MidiFeedbackPlugin):
|
||||
self.set_status(note=70, velocity=layer)
|
||||
|
||||
def feedback_show_modulation(self, slot):
|
||||
for i in range(self.NOTE_MODULATION_COLUMN,self.NOTE_MODULATION_COLUMN+4):
|
||||
if slot==i-self.NOTE_MODULATION_COLUMN:
|
||||
for i in range(self.NOTE_MODULATION_COLUMN, self.NOTE_MODULATION_COLUMN + 4):
|
||||
if slot == i - self.NOTE_MODULATION_COLUMN:
|
||||
self.set_status(note=i, velocity=self.COLOUR_GREEN)
|
||||
else:
|
||||
self.set_status(note=i, velocity=self.COLOUR_OFF)
|
||||
|
||||
def feedback_plugin_status(self):
|
||||
from data_centre.plugin_collection import SequencePlugin
|
||||
from data_centre.plugin_collection import SequencePlugin
|
||||
|
||||
try:
|
||||
from plugins.ShaderLoopRecordPlugin import ShaderLoopRecordPlugin
|
||||
for plugin in self.pc.get_plugins(SequencePlugin):
|
||||
if isinstance(plugin, ShaderLoopRecordPlugin):
|
||||
try:
|
||||
from plugins.ShaderLoopRecordPlugin import ShaderLoopRecordPlugin
|
||||
for plugin in self.pc.get_plugins(SequencePlugin):
|
||||
if isinstance(plugin, ShaderLoopRecordPlugin):
|
||||
|
||||
NOTE_PLAY_STATUS = 65
|
||||
NOTE_RECORD_STATUS = 66
|
||||
NOTE_OVERDUB_STATUS = 67
|
||||
#NOTE_CLIP_STATUS_ROW = 8
|
||||
NOTE_PLAY_STATUS = 65
|
||||
NOTE_RECORD_STATUS = 66
|
||||
NOTE_OVERDUB_STATUS = 67
|
||||
# NOTE_CLIP_STATUS_ROW = 8
|
||||
|
||||
colour = self.COLOUR_OFF
|
||||
if plugin.is_playing():
|
||||
colour = self.COLOUR_GREEN
|
||||
if plugin.is_paused():
|
||||
colour += self.BLINK
|
||||
self.set_status(command='note_on', note=NOTE_PLAY_STATUS, velocity=colour)
|
||||
|
||||
colour = self.COLOUR_OFF
|
||||
if plugin.recording:
|
||||
colour = self.COLOUR_GREEN
|
||||
if plugin.is_ignoring():
|
||||
colour += self.BLINK
|
||||
self.set_status(command='note_on', note=NOTE_RECORD_STATUS, velocity=colour)
|
||||
|
||||
colour = self.COLOUR_OFF
|
||||
if plugin.overdub:
|
||||
colour = self.COLOUR_RED
|
||||
if plugin.is_paused() or plugin.is_ignoring():
|
||||
colour += self.BLINK
|
||||
self.set_status(command='note_on', note=NOTE_OVERDUB_STATUS, velocity=colour)
|
||||
|
||||
for i in range(plugin.MAX_CLIPS):
|
||||
if i in plugin.running_clips:
|
||||
if plugin.is_playing() and not plugin.is_paused():
|
||||
colour = self.COLOUR_GREEN
|
||||
else:
|
||||
colour = self.COLOUR_AMBER
|
||||
if plugin.selected_clip==i: #blink if selected
|
||||
colour += self.BLINK
|
||||
elif plugin.selected_clip==i:
|
||||
colour = self.COLOUR_RED_BLINK
|
||||
else:
|
||||
colour = self.COLOUR_OFF
|
||||
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
|
||||
if plugin.is_playing() and not plugin.is_paused():
|
||||
for i in range(0,plugin.MAX_CLIPS):
|
||||
if i==int(plugin.position*plugin.MAX_CLIPS):
|
||||
self.set_status(command='note_on', note=self.NOTE_CLIP_STATUS_ROW+i, velocity=self.COLOUR_GREEN)
|
||||
"""
|
||||
except Exception as e:
|
||||
pass
|
||||
#print ("Warning: Failed when running plugin feedback for ShaderLoopRecordPlugin:\t%s" % str(e))
|
||||
|
||||
try:
|
||||
from plugins.ShaderQuickPresetPlugin import ShaderQuickPresetPlugin
|
||||
#print ("feedback_plugin_status")
|
||||
for plugin in self.pc.get_plugins(ShaderQuickPresetPlugin):
|
||||
#print ("for plugin %s" % plugin)
|
||||
for pad in range(0,8):
|
||||
#print ("checking selected_preset %s vs pad %s" % (plugin.selected_preset, pad))
|
||||
colour = self.COLOUR_OFF
|
||||
if plugin.presets[pad] is not None:
|
||||
colour = self.COLOUR_AMBER
|
||||
if plugin.last_recalled==pad:
|
||||
colour = self.COLOUR_OFF
|
||||
if plugin.is_playing():
|
||||
colour = self.COLOUR_GREEN
|
||||
if plugin.selected_preset==pad:
|
||||
if plugin.presets[pad] is None:
|
||||
if plugin.is_paused():
|
||||
colour += self.BLINK
|
||||
self.set_status(command='note_on', note=NOTE_PLAY_STATUS, velocity=colour)
|
||||
|
||||
colour = self.COLOUR_OFF
|
||||
if plugin.recording:
|
||||
colour = self.COLOUR_GREEN
|
||||
if plugin.is_ignoring():
|
||||
colour += self.BLINK
|
||||
self.set_status(command='note_on', note=NOTE_RECORD_STATUS, velocity=colour)
|
||||
|
||||
colour = self.COLOUR_OFF
|
||||
if plugin.overdub:
|
||||
colour = self.COLOUR_RED
|
||||
colour += self.BLINK
|
||||
self.set_status(command='note_on', note=self.NOTE_SHADER_PRESET_ROW+pad, velocity=colour)
|
||||
except Exception as e:
|
||||
pass
|
||||
#print ("Warning: Failed when running plugin feedback for ShaderQuickPresetPlugin:\t%s" % str(e))
|
||||
if plugin.is_paused() or plugin.is_ignoring():
|
||||
colour += self.BLINK
|
||||
self.set_status(command='note_on', note=NOTE_OVERDUB_STATUS, velocity=colour)
|
||||
|
||||
for i in range(plugin.MAX_CLIPS):
|
||||
if i in plugin.running_clips:
|
||||
if plugin.is_playing() and not plugin.is_paused():
|
||||
colour = self.COLOUR_GREEN
|
||||
else:
|
||||
colour = self.COLOUR_AMBER
|
||||
if plugin.selected_clip == i: # blink if selected
|
||||
colour += self.BLINK
|
||||
elif plugin.selected_clip == i:
|
||||
colour = self.COLOUR_RED_BLINK
|
||||
else:
|
||||
colour = self.COLOUR_OFF
|
||||
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
|
||||
if plugin.is_playing() and not plugin.is_paused():
|
||||
for i in range(0,plugin.MAX_CLIPS):
|
||||
if i==int(plugin.position*plugin.MAX_CLIPS):
|
||||
self.set_status(command='note_on', note=self.NOTE_CLIP_STATUS_ROW+i, velocity=self.COLOUR_GREEN)
|
||||
"""
|
||||
except Exception as e:
|
||||
pass
|
||||
# print ("Warning: Failed when running plugin feedback for ShaderLoopRecordPlugin:\t%s" % str(e))
|
||||
|
||||
try:
|
||||
from plugins.ShaderQuickPresetPlugin import ShaderQuickPresetPlugin
|
||||
# print ("feedback_plugin_status")
|
||||
for plugin in self.pc.get_plugins(ShaderQuickPresetPlugin):
|
||||
# print ("for plugin %s" % plugin)
|
||||
for pad in range(0, 8):
|
||||
# print ("checking selected_preset %s vs pad %s" % (plugin.selected_preset, pad))
|
||||
colour = self.COLOUR_OFF
|
||||
if plugin.presets[pad] is not None:
|
||||
colour = self.COLOUR_AMBER
|
||||
if plugin.last_recalled == pad:
|
||||
colour = self.COLOUR_GREEN
|
||||
if plugin.selected_preset == pad:
|
||||
if plugin.presets[pad] is None:
|
||||
colour = self.COLOUR_RED
|
||||
colour += self.BLINK
|
||||
self.set_status(command='note_on', note=self.NOTE_SHADER_PRESET_ROW + pad, velocity=colour)
|
||||
except Exception as e:
|
||||
pass
|
||||
# print ("Warning: Failed when running plugin feedback for ShaderQuickPresetPlugin:\t%s" % str(e))
|
||||
|
||||
BLINK = 1
|
||||
COLOUR_OFF = 0
|
||||
@@ -189,7 +190,7 @@ class MidiFeedbackAPCKey25Plugin(MidiFeedbackPlugin):
|
||||
# show if internal feedback (the shader layer kind) is enabled
|
||||
if self.pc.data.feedback_active and not self.pc.data.function_on:
|
||||
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)
|
||||
else:
|
||||
self.feedback_shader_feedback(self.COLOUR_OFF)
|
||||
@@ -204,16 +205,16 @@ class MidiFeedbackAPCKey25Plugin(MidiFeedbackPlugin):
|
||||
|
||||
self.feedback_plugin_status()
|
||||
|
||||
for n,shader in enumerate(self.pc.message_handler.shaders.selected_shader_list):
|
||||
#print ("%s: in refresh_midi_feedback, got shader: %s" % (n,shader))
|
||||
for n, shader in enumerate(self.pc.message_handler.shaders.selected_shader_list):
|
||||
# print ("%s: in refresh_midi_feedback, got shader: %s" % (n,shader))
|
||||
# show if layer is running or not
|
||||
if not self.pc.data.function_on:
|
||||
if self.pc.message_handler.shaders.selected_status_list[n] == '▶':
|
||||
self.feedback_shader_layer_on(n)
|
||||
else:
|
||||
self.feedback_shader_layer_off(n)
|
||||
for x in range(0,8):
|
||||
if 'slot' in shader and shader.get('slot',None)==x:
|
||||
for x in range(0, 8):
|
||||
if 'slot' in shader and shader.get('slot', None) == x:
|
||||
if self.pc.message_handler.shaders.selected_status_list[n] == '▶':
|
||||
# show that slot is selected and running
|
||||
self.feedback_shader_on(n, x, self.COLOUR_GREEN)
|
||||
@@ -229,15 +230,16 @@ class MidiFeedbackAPCKey25Plugin(MidiFeedbackPlugin):
|
||||
|
||||
self.update_device()
|
||||
|
||||
#print("refresh_midi_feedback")
|
||||
# print("refresh_midi_feedback")
|
||||
|
||||
last_state = None
|
||||
|
||||
def update_device(self):
|
||||
from copy import deepcopy
|
||||
#print("in update device status is %s" % self.status)
|
||||
for i,c in self.status.items():
|
||||
#'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):
|
||||
#print("got command: %s: %s" % (i,c))
|
||||
# print("in update device status is %s" % self.status)
|
||||
for i, c in self.status.items():
|
||||
# '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):
|
||||
# print("got command: %s: %s" % (i,c))
|
||||
self.send_command(**c)
|
||||
self.last_state = deepcopy(self.status)
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import plugins
|
||||
#from plugins.MidiFeedbackAPCKey25Plugin import MidiFeedbackAPCKey25Plugin
|
||||
|
||||
|
||||
# from plugins.MidiFeedbackAPCKey25Plugin import MidiFeedbackAPCKey25Plugin
|
||||
|
||||
class MidiFeedbackLaunchpadPlugin(plugins.MidiFeedbackAPCKey25Plugin.MidiFeedbackAPCKey25Plugin):
|
||||
|
||||
status = {}
|
||||
|
||||
def __init__(self, plugin_collection):
|
||||
@@ -10,15 +11,15 @@ class MidiFeedbackLaunchpadPlugin(plugins.MidiFeedbackAPCKey25Plugin.MidiFeedbac
|
||||
self.description = 'Outputs feedback to Novation Launchpad'
|
||||
|
||||
def init_notes(self):
|
||||
self.NOTE_PLAY_SHADER = self.get_note('play_shader_0_0',0)
|
||||
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_PLAY_SHADER = self.get_note('play_shader_0_0', 0)
|
||||
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_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_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_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):
|
||||
@@ -28,16 +29,17 @@ class MidiFeedbackLaunchpadPlugin(plugins.MidiFeedbackAPCKey25Plugin.MidiFeedbac
|
||||
return True
|
||||
|
||||
def feedback_shader_on(self, layer, slot, colour=None):
|
||||
if colour is None: colour = self.COLOUR_GREEN
|
||||
self.set_status(note=(self.NOTE_PLAY_SHADER+(layer)*16)+slot, velocity=int(colour))
|
||||
if colour is None:
|
||||
colour = self.COLOUR_GREEN
|
||||
self.set_status(note=(self.NOTE_PLAY_SHADER + (layer) * 16) + slot, velocity=int(colour))
|
||||
|
||||
def feedback_shader_off(self, layer, slot):
|
||||
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
|
||||
BLINK = 1
|
||||
COLOUR_OFF = 0
|
||||
COLOUR_GREEN = 8 #1
|
||||
COLOUR_GREEN = 8 # 1
|
||||
COLOUR_GREEN_BLINK = 15
|
||||
COLOUR_RED = 32
|
||||
COLOUR_RED_BLINK = 47
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
from data_centre.plugin_collection import ActionsPlugin
|
||||
|
||||
|
||||
class MultiActionsPlugin(ActionsPlugin):
|
||||
disabled = False # this is only a demo of very basic multi-actions plugin -- superceded by ManipulatePlugin
|
||||
disabled = False # this is only a demo of very basic multi-actions plugin -- superceded by ManipulatePlugin
|
||||
|
||||
def __init__(self, plugin_collection):
|
||||
super().__init__(plugin_collection)
|
||||
try:
|
||||
from plugins import ManipulatePlugin
|
||||
self.disabled = True # if we've found ManipulatePlugin then disable this one
|
||||
self.disabled = True # if we've found ManipulatePlugin then disable this one
|
||||
except:
|
||||
# if it fails, we're good to go (so long as not disabled explictly above)
|
||||
pass
|
||||
@@ -15,7 +16,7 @@ class MultiActionsPlugin(ActionsPlugin):
|
||||
@property
|
||||
def parserlist(self):
|
||||
return [
|
||||
( r"(.*)&&(.*)", self.run_multi ),
|
||||
(r"(.*)&&(.*)", self.run_multi),
|
||||
]
|
||||
|
||||
def run_multi(self, action1, action2, value):
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
from data_centre.plugin_collection import ActionsPlugin, SequencePlugin, DisplayPlugin
|
||||
from data_centre.plugin_collection import ActionsPlugin, DisplayPlugin, SequencePlugin
|
||||
from plugins.frame_manager import Frame
|
||||
|
||||
|
||||
class ShaderLoopRecordPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin):
|
||||
|
||||
class ShaderLoopRecordPlugin(ActionsPlugin, SequencePlugin, DisplayPlugin):
|
||||
MAX_CLIPS = 8
|
||||
frames = []
|
||||
frames = []
|
||||
|
||||
def __init__(self, plugin_collection):
|
||||
super().__init__(plugin_collection)
|
||||
@@ -21,25 +20,25 @@ class ShaderLoopRecordPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin):
|
||||
self.reset_ignored()
|
||||
|
||||
def load_presets(self):
|
||||
#try:
|
||||
# try:
|
||||
print("trying load presets? %s " % self.PRESET_FILE_NAME)
|
||||
p = self.pc.read_json(self.PRESET_FILE_NAME)
|
||||
if p:
|
||||
while len(p)<self.MAX_CLIPS:
|
||||
print ("adding clip ")
|
||||
p += self.get_empty_clip(self.duration) #[ [None] ] #*((int(self.duration / self.frequency))-len(p)) ]
|
||||
while len(p) < self.MAX_CLIPS:
|
||||
print("adding clip ")
|
||||
p += self.get_empty_clip(self.duration) # [ [None] ] #*((int(self.duration / self.frequency))-len(p)) ]
|
||||
for i in p:
|
||||
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")
|
||||
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))
|
||||
return p
|
||||
elif p:
|
||||
return p
|
||||
else:
|
||||
return self.get_factory_reset()
|
||||
#except:
|
||||
# except:
|
||||
# return self.clear_frames()
|
||||
|
||||
def save_presets(self):
|
||||
@@ -51,72 +50,69 @@ class ShaderLoopRecordPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin):
|
||||
|
||||
# DisplayPlugin methods
|
||||
def get_display_modes(self):
|
||||
return ['LOOPREC','NAV_LPRC']
|
||||
return ['LOOPREC', 'NAV_LPRC']
|
||||
|
||||
def show_plugin(self, display, display_mode):
|
||||
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, "test from ShaderLoopRecordPlugin!\n")
|
||||
status = ""
|
||||
status+="playing" if self.is_playing() else "stopped"
|
||||
status+="\t"
|
||||
status+="paused" if self.is_paused() else "unpaused"
|
||||
status+="\t"
|
||||
status+="REC" if self.recording else "---"
|
||||
status+="*" if self.is_ignoring() else " "
|
||||
status+="\t"
|
||||
status+="Overdub" if self.overdub else "-------"
|
||||
status+="\t"
|
||||
status+="Looping" if self.looping else "Once"
|
||||
status+="\n"
|
||||
status += "playing" if self.is_playing() else "stopped"
|
||||
status += "\t"
|
||||
status += "paused" if self.is_paused() else "unpaused"
|
||||
status += "\t"
|
||||
status += "REC" if self.recording else "---"
|
||||
status += "*" if self.is_ignoring() else " "
|
||||
status += "\t"
|
||||
status += "Overdub" if self.overdub else "-------"
|
||||
status += "\t"
|
||||
status += "Looping" if self.looping else "Once"
|
||||
status += "\n"
|
||||
|
||||
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, (" 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)))
|
||||
if self.speed==0.0:
|
||||
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:{} {:3.0f}%\n".format(display.get_speed_indicator(self.speed / 2, convert=False), self.speed * 100)))
|
||||
if self.speed == 0.0:
|
||||
display.display_text.insert(END, ("Duration:\tinfinity!\n"))
|
||||
else:
|
||||
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
|
||||
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
|
||||
|
||||
status = "\nEnabled clips:\t"
|
||||
for i in range(0,self.MAX_CLIPS):
|
||||
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 in self.running_clips else\
|
||||
'_'
|
||||
for i in range(0, self.MAX_CLIPS):
|
||||
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 in self.running_clips else \
|
||||
'_'
|
||||
status += "\n"
|
||||
display.display_text.insert(END, status)
|
||||
|
||||
|
||||
"""for key,value in self.variables.items():
|
||||
display.display_text.insert(END, "\t" + key + "\t{:03.2f}\n".format(value))"""
|
||||
|
||||
|
||||
|
||||
@property
|
||||
def parserlist(self):
|
||||
return [
|
||||
( r"run_automation", self.run_automation ),
|
||||
( r"stop_automation", self.stop_automation ),
|
||||
( r"toggle_pause_automation", self.toggle_pause_automation ),
|
||||
( r"pause_automation", self.pause_automation ),
|
||||
( r"toggle_loop_automation", self.toggle_loop_automation ),
|
||||
( r"set_automation_speed", self.set_speed ),
|
||||
( r"toggle_record_automation", self.toggle_record_automation ),
|
||||
( r"toggle_overdub_automation", self.toggle_overdub_automation ),
|
||||
( r"clear_automation", self.clear_clip ),
|
||||
( r"select_automation_clip_([0-7])", self.select_clip ),
|
||||
( r"toggle_automation_clip_([0-7])", self.toggle_clip ),
|
||||
#( r"smooth_clip_(0-7])", self.smooth_clip ),
|
||||
( r"smooth_selected_clip", self.smooth_selected_clip )
|
||||
(r"run_automation", self.run_automation),
|
||||
(r"stop_automation", self.stop_automation),
|
||||
(r"toggle_pause_automation", self.toggle_pause_automation),
|
||||
(r"pause_automation", self.pause_automation),
|
||||
(r"toggle_loop_automation", self.toggle_loop_automation),
|
||||
(r"set_automation_speed", self.set_speed),
|
||||
(r"toggle_record_automation", self.toggle_record_automation),
|
||||
(r"toggle_overdub_automation", self.toggle_overdub_automation),
|
||||
(r"clear_automation", self.clear_clip),
|
||||
(r"select_automation_clip_([0-7])", self.select_clip),
|
||||
(r"toggle_automation_clip_([0-7])", self.toggle_clip),
|
||||
# ( r"smooth_clip_(0-7])", self.smooth_clip ),
|
||||
(r"smooth_selected_clip", self.smooth_selected_clip)
|
||||
]
|
||||
|
||||
def smooth_selected_clip(self):
|
||||
self.pc.fm.interpolate_clip(self.frames[self.selected_clip])
|
||||
|
||||
|
||||
def toggle_overdub_automation(self):
|
||||
self.overdub = not self.overdub
|
||||
if not self.overdub:
|
||||
@@ -132,36 +128,37 @@ class ShaderLoopRecordPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin):
|
||||
self.last_saved_index = None
|
||||
self.save_presets()
|
||||
|
||||
def get_empty_clip(self, duration = 4000):
|
||||
def get_empty_clip(self, duration=4000):
|
||||
return [None] * (int(duration / self.frequency))
|
||||
|
||||
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:
|
||||
clip = self.selected_clip
|
||||
self.frames[clip] = self.get_empty_clip(self.duration) * self.MAX_CLIPS
|
||||
self.reset_ignored()
|
||||
if self.DEBUG_FRAMES: print ("clear_frames set to %s" % (int(self.duration / self.frequency)))
|
||||
if self.DEBUG_FRAMES:
|
||||
print("clear_frames set to %s" % (int(self.duration / self.frequency)))
|
||||
return self.frames
|
||||
|
||||
def toggle_clip(self,clip = None):
|
||||
def toggle_clip(self, clip=None):
|
||||
if clip is None:
|
||||
clip = self.selected_clip
|
||||
else:
|
||||
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:
|
||||
self.running_clips.remove(clip)
|
||||
else:
|
||||
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):
|
||||
# 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):
|
||||
return not self.pc.fm.is_frame_empty(self.ignored)
|
||||
@@ -170,81 +167,92 @@ class ShaderLoopRecordPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin):
|
||||
self.selected_clip = clip
|
||||
|
||||
selected_clip = 0
|
||||
running_clips = [ ] #False ] * self.MAX_CLIPS
|
||||
running_clips = [] # False ] * self.MAX_CLIPS
|
||||
|
||||
duration = 4000
|
||||
frequency = 10 #25
|
||||
frequency = 10 # 25
|
||||
recording = False
|
||||
overdub = True
|
||||
#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_saved_index = None # for backfilling
|
||||
DEBUG_FRAMES = False#True
|
||||
overdub = True
|
||||
# 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_saved_index = None # for backfilling
|
||||
DEBUG_FRAMES = False # True
|
||||
|
||||
def run_sequence(self, position):
|
||||
current_frame_index = int(position * (int(self.duration / self.frequency)))
|
||||
if current_frame_index<0:
|
||||
current_frame_index = (self.duration/self.frequency) - current_frame_index
|
||||
if current_frame_index >= self.duration: # self.duration/self.frequency:
|
||||
current_frame_index = "(self.duration/self.frequency) +""" (current_frame_index%self.duration)
|
||||
if current_frame_index < 0:
|
||||
current_frame_index = (self.duration / self.frequency) - current_frame_index
|
||||
if current_frame_index >= self.duration: # self.duration/self.frequency:
|
||||
current_frame_index = "(self.duration/self.frequency) +"""(current_frame_index % self.duration)
|
||||
|
||||
if self.DEBUG_FRAMES: print (">>>>>>>>>>>>>>frame at %i%%: %i" % (position*100, current_frame_index))
|
||||
#print("got frame index %s" % current_frame_index)
|
||||
if self.DEBUG_FRAMES:
|
||||
print(">>>>>>>>>>>>>>frame at %i%%: %i" % (position * 100, current_frame_index))
|
||||
# print("got frame index %s" % current_frame_index)
|
||||
|
||||
if self.recording:
|
||||
current_frame = self.pc.fm.get_live_frame() #.copy()
|
||||
current_frame = self.pc.fm.get_live_frame() # .copy()
|
||||
|
||||
selected_clip = self.selected_clip
|
||||
if self.DEBUG_FRAMES: print("current_frame copy before recall is %s" % current_frame['shader_params'])
|
||||
#print ("%s clips, looks like %s" % (len(self.frames),self.frames))
|
||||
if self.DEBUG_FRAMES:
|
||||
print("current_frame copy before recall is %s" % current_frame['shader_params'])
|
||||
# print ("%s clips, looks like %s" % (len(self.frames),self.frames))
|
||||
|
||||
#print("selected_clip is %s "%selected_clip)
|
||||
#clip = self.frames[selected_clip]
|
||||
# print("selected_clip is %s "%selected_clip)
|
||||
# clip = self.frames[selected_clip]
|
||||
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:
|
||||
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'])
|
||||
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'])
|
||||
|
||||
for selected_clip in self.running_clips:
|
||||
saved_frame = self.frames[selected_clip][current_frame_index]
|
||||
if not self.recording or (selected_clip!=self.selected_clip):
|
||||
self.pc.fm.recall_frame(saved_frame)
|
||||
if self.recording and selected_clip==self.selected_clip:
|
||||
if self.last_frame is None:
|
||||
self.last_frame = current_frame
|
||||
if self.DEBUG_FRAMES: print("last frame is \t\t%s" % self.last_frame['shader_params'])
|
||||
if self.DEBUG_FRAMES: print("current f is \t\t%s" % current_frame['shader_params'])
|
||||
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'])
|
||||
saved_frame = self.frames[selected_clip][current_frame_index]
|
||||
if not self.recording or (selected_clip != self.selected_clip):
|
||||
self.pc.fm.recall_frame(saved_frame)
|
||||
if self.recording and selected_clip == self.selected_clip:
|
||||
if self.last_frame is None:
|
||||
self.last_frame = current_frame
|
||||
if self.DEBUG_FRAMES:
|
||||
print("last frame is \t\t%s" % self.last_frame['shader_params'])
|
||||
if self.DEBUG_FRAMES:
|
||||
print("current f is \t\t%s" % current_frame['shader_params'])
|
||||
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:
|
||||
# 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'])
|
||||
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))
|
||||
"""print("got self.ignored:\n\t%s\n" % self.ignored.f)
|
||||
print("diff is currently:\n\t%s\n" % diff.f)
|
||||
print("saved_frame is currently:\n\t%s\n" % saved_frame.f)"""
|
||||
diff = self.pc.fm.merge_frames(
|
||||
self.pc.fm.get_frame_ignored(saved_frame, self.ignored),
|
||||
diff
|
||||
)
|
||||
#print("got merged:\n\t%s\n" % diff.f)
|
||||
#diff = self.pc.shaders.merge_frames(self.pc.shaders.get_live_frame(), diff)
|
||||
self.pc.fm.recall_frame(diff)
|
||||
if self.DEBUG_FRAMES: print("after diff2 is: \t%s" % diff['shader_params'])
|
||||
if self.DEBUG_FRAMES: print("||||saving frame \t%s" % (diff['shader_params']))
|
||||
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.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) ):
|
||||
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.last_saved_index = current_frame_index
|
||||
self.last_frame = self.pc.fm.get_live_frame() #diff
|
||||
if self.DEBUG_FRAMES: print("<<<<<<<<<<<<<< frame at %s" % current_frame_index)
|
||||
if self.overdub and saved_frame:
|
||||
# add the params tweaked this frame to the params to be ignored by recall
|
||||
if self.DEBUG_FRAMES:
|
||||
print("saved frame is \t%s" % saved_frame['shader_params'])
|
||||
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))
|
||||
"""print("got self.ignored:\n\t%s\n" % self.ignored.f)
|
||||
print("diff is currently:\n\t%s\n" % diff.f)
|
||||
print("saved_frame is currently:\n\t%s\n" % saved_frame.f)"""
|
||||
diff = self.pc.fm.merge_frames(
|
||||
self.pc.fm.get_frame_ignored(saved_frame, self.ignored),
|
||||
diff
|
||||
)
|
||||
# print("got merged:\n\t%s\n" % diff.f)
|
||||
# diff = self.pc.shaders.merge_frames(self.pc.shaders.get_live_frame(), diff)
|
||||
self.pc.fm.recall_frame(diff)
|
||||
if self.DEBUG_FRAMES:
|
||||
print("after diff2 is: \t%s" % diff['shader_params'])
|
||||
if self.DEBUG_FRAMES:
|
||||
print("||||saving frame \t%s" % (diff['shader_params']))
|
||||
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.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) ):
|
||||
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.last_saved_index = current_frame_index
|
||||
self.last_frame = self.pc.fm.get_live_frame() # diff
|
||||
if self.DEBUG_FRAMES:
|
||||
print("<<<<<<<<<<<<<< frame at %s" % current_frame_index)
|
||||
|
||||
"""def recall_frame_index(self, index):
|
||||
self.pc.shaders.recall_frame_params(self.frames[index].copy())"""
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
from data_centre.plugin_collection import ActionsPlugin, DisplayPlugin
|
||||
from plugins.frame_manager import Frame
|
||||
|
||||
class ShaderQuickPresetPlugin(ActionsPlugin,DisplayPlugin): #,SequencePlugin):
|
||||
|
||||
class ShaderQuickPresetPlugin(ActionsPlugin, DisplayPlugin): # ,SequencePlugin):
|
||||
|
||||
MAX_PRESETS = 8
|
||||
display_live_on = False
|
||||
@@ -18,7 +19,7 @@ class ShaderQuickPresetPlugin(ActionsPlugin,DisplayPlugin): #,SequencePlugin):
|
||||
|
||||
def load_presets(self):
|
||||
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):
|
||||
self.pc.update_json(self.PRESET_FILE_NAME, self.presets)
|
||||
@@ -29,20 +30,20 @@ class ShaderQuickPresetPlugin(ActionsPlugin,DisplayPlugin): #,SequencePlugin):
|
||||
|
||||
@property
|
||||
def parserlist(self):
|
||||
return [
|
||||
( r"load_presets", self.load_presets ),
|
||||
( r"save_presets", self.save_presets ),
|
||||
( r"store_next_preset", self.store_next_preset ),
|
||||
( r"store_current_preset", self.store_current_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"clear_current_preset", self.clear_current_preset ),
|
||||
( r"qksh_toggle_display_live", self.toggle_display_live ),
|
||||
( r"switch_to_next_preset", self.switch_to_next_preset ),
|
||||
( r"switch_to_previous_preset", self.switch_to_previous_preset ),
|
||||
( r"switch_to_current_preset", self.switch_to_current_preset ),
|
||||
( r"select_previous_preset", self.select_previous_preset ),
|
||||
( r"select_next_preset", self.select_next_preset ),
|
||||
return [
|
||||
(r"load_presets", self.load_presets),
|
||||
(r"save_presets", self.save_presets),
|
||||
(r"store_next_preset", self.store_next_preset),
|
||||
(r"store_current_preset", self.store_current_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"clear_current_preset", self.clear_current_preset),
|
||||
(r"qksh_toggle_display_live", self.toggle_display_live),
|
||||
(r"switch_to_next_preset", self.switch_to_next_preset),
|
||||
(r"switch_to_previous_preset", self.switch_to_previous_preset),
|
||||
(r"switch_to_current_preset", self.switch_to_current_preset),
|
||||
(r"select_previous_preset", self.select_previous_preset),
|
||||
(r"select_next_preset", self.select_next_preset),
|
||||
]
|
||||
|
||||
def toggle_display_live(self):
|
||||
@@ -50,16 +51,16 @@ class ShaderQuickPresetPlugin(ActionsPlugin,DisplayPlugin): #,SequencePlugin):
|
||||
|
||||
# DisplayPlugin methods
|
||||
def get_display_modes(self):
|
||||
return ['QUIKSHDR',['NAV_QKSH','PLAY_SHADER']]
|
||||
return ['QUIKSHDR', ['NAV_QKSH', 'PLAY_SHADER']]
|
||||
|
||||
def show_plugin(self, display, display_mode):
|
||||
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, "ShaderQuickPresetPlugin")
|
||||
|
||||
status = "Selected: ["
|
||||
#for i,preset in enumerate(self.presets):
|
||||
# for i,preset in enumerate(self.presets):
|
||||
for i in range(self.MAX_PRESETS):
|
||||
preset = self.presets[i]
|
||||
if i == self.selected_preset:
|
||||
@@ -81,14 +82,14 @@ class ShaderQuickPresetPlugin(ActionsPlugin,DisplayPlugin): #,SequencePlugin):
|
||||
display.display_text.insert(END, "Showing LIVE preview\n")
|
||||
else:
|
||||
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, "\n")
|
||||
|
||||
## show a summary of the selected preset
|
||||
if self.selected_preset is not None:
|
||||
# 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():
|
||||
display.display_text.insert(END, "%s\n" % line)
|
||||
|
||||
@@ -99,7 +100,7 @@ class ShaderQuickPresetPlugin(ActionsPlugin,DisplayPlugin): #,SequencePlugin):
|
||||
# didnt find an empty slot, save to current
|
||||
self.store_current_preset()
|
||||
self.selected_preset += 1
|
||||
self.selected_preset %= self.MAX_PRESETS
|
||||
self.selected_preset %= self.MAX_PRESETS
|
||||
else:
|
||||
# found an empty slot, save to it
|
||||
self.selected_preset = res[0]
|
||||
@@ -113,11 +114,12 @@ class ShaderQuickPresetPlugin(ActionsPlugin,DisplayPlugin): #,SequencePlugin):
|
||||
self.save_presets()
|
||||
|
||||
def store_current_preset(self):
|
||||
if self.selected_preset is None: self.selected_preset = 0
|
||||
if self.selected_preset is None:
|
||||
self.selected_preset = 0
|
||||
|
||||
insert_position = self.selected_preset
|
||||
self.presets[insert_position] = self.pc.fm.get_live_frame()
|
||||
#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.last_recalled = insert_position
|
||||
|
||||
@@ -127,18 +129,18 @@ class ShaderQuickPresetPlugin(ActionsPlugin,DisplayPlugin): #,SequencePlugin):
|
||||
self.selected_preset = preset
|
||||
|
||||
def switch_to_preset(self, preset):
|
||||
#if preset>len(self.presets):
|
||||
# if preset>len(self.presets):
|
||||
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
|
||||
return
|
||||
print ("switching to preset %s" % preset)
|
||||
print("switching to preset %s" % preset)
|
||||
self.selected_preset = preset
|
||||
|
||||
self.last_recalled = preset
|
||||
preset = self.presets[preset]
|
||||
|
||||
print ("recalled preset %s" % preset)
|
||||
print("recalled preset %s" % preset)
|
||||
self.pc.fm.recall_frame(preset)
|
||||
|
||||
def switch_to_current_preset(self):
|
||||
@@ -158,7 +160,7 @@ class ShaderQuickPresetPlugin(ActionsPlugin,DisplayPlugin): #,SequencePlugin):
|
||||
self.selected_preset = 0
|
||||
return
|
||||
self.selected_preset += 1
|
||||
if self.selected_preset>=self.MAX_PRESETS:
|
||||
if self.selected_preset >= self.MAX_PRESETS:
|
||||
self.selected_preset = 0
|
||||
|
||||
def select_previous_preset(self):
|
||||
@@ -166,8 +168,5 @@ class ShaderQuickPresetPlugin(ActionsPlugin,DisplayPlugin): #,SequencePlugin):
|
||||
self.selected_preset = self.MAX_PRESETS
|
||||
return
|
||||
self.selected_preset -= 1
|
||||
if self.selected_preset<0:
|
||||
self.selected_preset = self.MAX_PRESETS-1
|
||||
|
||||
|
||||
|
||||
if self.selected_preset < 0:
|
||||
self.selected_preset = self.MAX_PRESETS - 1
|
||||
|
||||
@@ -5,12 +5,12 @@ import pyaudio
|
||||
|
||||
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
|
||||
|
||||
active = True
|
||||
@@ -19,15 +19,15 @@ class SoundReactPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin):
|
||||
|
||||
stream = None
|
||||
|
||||
CHUNK = 4096 # number of data points to read at a time
|
||||
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
|
||||
CHUNK = 4096 # number of data points to read at a time
|
||||
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
|
||||
|
||||
values = {}
|
||||
levels = {
|
||||
"energy": [ 0.0, 0.0, 1.0, 0.0 ],
|
||||
"peakfreq": [ 0.0, 0.0, 0.0, 0.0 ]
|
||||
"energy": [0.0, 0.0, 1.0, 0.0],
|
||||
"peakfreq": [0.0, 0.0, 0.0, 0.0]
|
||||
}
|
||||
last_values = {}
|
||||
display_values = {}
|
||||
@@ -44,9 +44,9 @@ class SoundReactPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin):
|
||||
|
||||
self.PRESET_FILE_NAME = "SoundReactPlugin/config.json"
|
||||
presets = self.load_presets()
|
||||
self.config = presets.get('config',self.config)
|
||||
self.levels = presets.get('levels',self.levels)
|
||||
self.active = presets.get('active',self.active)
|
||||
self.config = presets.get('config', self.config)
|
||||
self.levels = presets.get('levels', self.levels)
|
||||
self.active = presets.get('active', self.active)
|
||||
|
||||
if not self.disabled:
|
||||
self.start_plugin()
|
||||
@@ -56,7 +56,7 @@ class SoundReactPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin):
|
||||
return self.pc.read_json(self.PRESET_FILE_NAME) or {}
|
||||
|
||||
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):
|
||||
super().stop_plugin()
|
||||
@@ -73,9 +73,9 @@ class SoundReactPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin):
|
||||
|
||||
def open_sound_device(self):
|
||||
try:
|
||||
self.p=pyaudio.PyAudio()
|
||||
self.stream=self.p.open(format=pyaudio.paInt16,channels=1,rate=self.RATE,input=True,
|
||||
frames_per_buffer=self.CHUNK)
|
||||
self.p = pyaudio.PyAudio()
|
||||
self.stream = self.p.open(format=pyaudio.paInt16, channels=1, rate=self.RATE, input=True,
|
||||
frames_per_buffer=self.CHUNK)
|
||||
except:
|
||||
print("Failed to open sound device - disabling SoundReactPlugin!")
|
||||
self.active = False
|
||||
@@ -96,10 +96,10 @@ class SoundReactPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin):
|
||||
# TODO: write more interpreters
|
||||
return {
|
||||
"energy": self.energy,
|
||||
#"low": self.low,
|
||||
#"mid": self.mid,
|
||||
#"high": self.high,
|
||||
#"peakfreq": self.peakfreq
|
||||
# "low": self.low,
|
||||
# "mid": self.mid,
|
||||
# "high": self.high,
|
||||
# "peakfreq": self.peakfreq
|
||||
}
|
||||
|
||||
# triggers?
|
||||
@@ -107,127 +107,128 @@ class SoundReactPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin):
|
||||
|
||||
# DisplayPlugin methods
|
||||
def get_display_modes(self):
|
||||
return ['SOUNDMOD','NAV_SND']
|
||||
return ['SOUNDMOD', 'NAV_SND']
|
||||
|
||||
def show_plugin(self, display, display_mode):
|
||||
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, "SoundReactPlugin - ")
|
||||
|
||||
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):
|
||||
value = "{:8}:\t".format(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)
|
||||
for i, level in enumerate(self.levels[sourcename]):
|
||||
g = self.pc.display.get_mod_slot_label(i) + '%s ' % self.pc.display.get_bar(level)
|
||||
value += g
|
||||
value += "\t"
|
||||
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")
|
||||
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, "%s\n" %self.last_lfo_status[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")
|
||||
|
||||
energy_history = []
|
||||
|
||||
def run_sequence(self, position):
|
||||
# position is irrelvant for this plugin, we just want to run continuously
|
||||
if not self.active or self.stream is None:
|
||||
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 = {}
|
||||
|
||||
for sourcename in self.sources:
|
||||
value = self.sources[sourcename](data)
|
||||
self.values[sourcename] = value
|
||||
if value is None:
|
||||
if value is None:
|
||||
continue
|
||||
for slot,level in enumerate(self.levels.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])
|
||||
for slot, level in enumerate(self.levels.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])
|
||||
previous_value[sourcename] = self.last_values.get(sourcename) or value
|
||||
self.last_values[sourcename] = self.values[sourcename]
|
||||
|
||||
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))
|
||||
if len(self.energy_history)>5: #self.duration:
|
||||
meandiff = abs(diff-mean(self.energy_history[:int(len(self.energy_history)/2)]))
|
||||
#print (" diff is %s, meandiff %s" % (diff, meandiff))
|
||||
if meandiff>=self.config['energy'].get('triggerthreshold',0.15):
|
||||
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:
|
||||
meandiff = abs(diff - mean(self.energy_history[:int(len(self.energy_history) / 2)]))
|
||||
# print (" diff is %s, meandiff %s" % (diff, meandiff))
|
||||
if meandiff >= self.config['energy'].get('triggerthreshold', 0.15):
|
||||
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..
|
||||
#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))
|
||||
#print("logging %s" % diff) #self.values.get(sourcename,0.0))
|
||||
# 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))
|
||||
# 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
|
||||
def energy(self,data):
|
||||
peak=np.average(np.abs(data))*2
|
||||
value = (peak/2**16)/16 * 100
|
||||
|
||||
def energy(self, data):
|
||||
peak = np.average(np.abs(data)) * 2
|
||||
value = (peak / 2 ** 16) / 16 * 100
|
||||
|
||||
value *= (self.GAIN_MULT * self.config['energy']['gain'])
|
||||
|
||||
value = value - self.config['energy']['threshold']
|
||||
if value<0.0:
|
||||
if value < 0.0:
|
||||
value = 0.0
|
||||
if value>1.0:
|
||||
if value > 1.0:
|
||||
value = 1.0
|
||||
|
||||
bars="#"*int(50*value)
|
||||
if self.DEBUG: print("energy:\t\t%05d %s\t(converted to %s)"%(peak,bars,value))
|
||||
bars = "#" * int(50 * value)
|
||||
if self.DEBUG:
|
||||
print("energy:\t\t%05d %s\t(converted to %s)" % (peak, bars, value))
|
||||
self.display_values['energy'] = "{} gn:{} trsh:{} trg:{}".format(
|
||||
self.pc.display.get_bar(value),
|
||||
self.pc.display.get_bar(self.config['energy']['gain']),
|
||||
self.pc.display.get_bar(self.config['energy']['threshold']),
|
||||
self.pc.display.get_bar(self.config['energy'].setdefault('triggerthreshold',0.15))
|
||||
)
|
||||
|
||||
return value
|
||||
|
||||
# dont think this works properly, or maybe it do just be like that
|
||||
def peakfreq(self,data):
|
||||
data = data.copy() * np.hanning(len(data)) # smooth the FFT by windowing data
|
||||
fft = abs(np.fft.fft(data).real)
|
||||
fft = fft[:int(len(fft)/2)] # keep only first half
|
||||
freq = np.fft.fftfreq(self.CHUNK,1.0/self.RATE)
|
||||
freq = freq[:int(len(freq)/2)] # keep only first half
|
||||
freqPeak = freq[np.where(fft==np.max(fft))[0][0]]+1
|
||||
if freqPeak<400:
|
||||
return False
|
||||
value = freqPeak/2000 # ?
|
||||
#value = (value**16)
|
||||
if self.DEBUG: print("peak frequency:\t%d\tHz\t(converted to %s)"%(freqPeak,value))
|
||||
self.display_values['peakfreq'] = ("%d Hz\t"%freqPeak) + "{:03.2f}".format(value)
|
||||
self.pc.display.get_bar(value),
|
||||
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'].setdefault('triggerthreshold', 0.15))
|
||||
)
|
||||
|
||||
return value
|
||||
|
||||
# dont think this works properly, or maybe it do just be like that
|
||||
|
||||
def peakfreq(self, data):
|
||||
data = data.copy() * np.hanning(len(data)) # smooth the FFT by windowing data
|
||||
fft = abs(np.fft.fft(data).real)
|
||||
fft = fft[:int(len(fft) / 2)] # keep only first half
|
||||
freq = np.fft.fftfreq(self.CHUNK, 1.0 / self.RATE)
|
||||
freq = freq[:int(len(freq) / 2)] # keep only first half
|
||||
freqPeak = freq[np.where(fft == np.max(fft))[0][0]] + 1
|
||||
if freqPeak < 400:
|
||||
return False
|
||||
value = freqPeak / 2000 # ?
|
||||
# value = (value**16)
|
||||
if self.DEBUG:
|
||||
print("peak frequency:\t%d\tHz\t(converted to %s)" % (freqPeak, value))
|
||||
self.display_values['peakfreq'] = ("%d Hz\t" % freqPeak) + "{:03.2f}".format(value)
|
||||
|
||||
return value
|
||||
|
||||
# ActionsPlugin methods
|
||||
@property
|
||||
def parserlist(self):
|
||||
return [
|
||||
( r"^toggle_sound_react_active$", self.toggle_active ),
|
||||
( 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"^toggle_sound_react_active$", self.toggle_active),
|
||||
(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),
|
||||
]
|
||||
|
||||
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):
|
||||
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!")
|
||||
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!")
|
||||
self.config[sourcename][setting] = value
|
||||
|
||||
def toggle_active(self):
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from data_centre.plugin_collection import ActionsPlugin, SequencePlugin
|
||||
|
||||
class TestPlugin(ActionsPlugin,SequencePlugin):
|
||||
|
||||
class TestPlugin(ActionsPlugin, SequencePlugin):
|
||||
disabled = True
|
||||
|
||||
def __init__(self, plugin_collection):
|
||||
@@ -8,39 +9,41 @@ class TestPlugin(ActionsPlugin,SequencePlugin):
|
||||
|
||||
@property
|
||||
def parserlist(self):
|
||||
return [
|
||||
( r"^test_plugin$", self.test_plugin ),
|
||||
( r"^cycle_shaders$", self.cycle_shaders ),
|
||||
( r"^run_automation$", self.run_automation ),
|
||||
( r"^stop_automation$", self.stop_automation ),
|
||||
( r"^toggle_pause_automation$", self.toggle_pause_automation ),
|
||||
( r"^pause_automation$", self.pause_automation ),
|
||||
( r"^toggle_loop_automation$", self.toggle_loop_automation ),
|
||||
( 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 )
|
||||
return [
|
||||
(r"^test_plugin$", self.test_plugin),
|
||||
(r"^cycle_shaders$", self.cycle_shaders),
|
||||
(r"^run_automation$", self.run_automation),
|
||||
(r"^stop_automation$", self.stop_automation),
|
||||
(r"^toggle_pause_automation$", self.toggle_pause_automation),
|
||||
(r"^pause_automation$", self.pause_automation),
|
||||
(r"^toggle_loop_automation$", self.toggle_loop_automation),
|
||||
(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)
|
||||
]
|
||||
|
||||
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
|
||||
|
||||
cycle_count = 0
|
||||
|
||||
def cycle_shaders(self):
|
||||
print ("Cycle shaders!!!")
|
||||
if self.cycle_count>9:
|
||||
print("Cycle shaders!!!")
|
||||
if self.cycle_count > 9:
|
||||
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(
|
||||
"play_shader_%s_%s" % (i, self.cycle_count), None
|
||||
"play_shader_%s_%s" % (i, self.cycle_count), None
|
||||
)
|
||||
self.pc.actions.call_method_name(
|
||||
"start_shader_layer_%s" % i, None
|
||||
"start_shader_layer_%s" % i, None
|
||||
)
|
||||
self.cycle_count += 1
|
||||
|
||||
duration = 5000
|
||||
frequency = 50
|
||||
|
||||
def run_sequence(self, position):
|
||||
self.pc.actions.call_method_name(
|
||||
"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):
|
||||
# invert the value
|
||||
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:
|
||||
# "toggle_automation_pause", None
|
||||
)
|
||||
|
||||
@@ -9,6 +9,7 @@ from data_centre.plugin_collection import ActionsPlugin, AutomationSourcePlugin,
|
||||
class AsyncWriter(threading.Thread):
|
||||
queue = []
|
||||
quit_flag = False
|
||||
|
||||
def __init__(self, plugin):
|
||||
super().__init__()
|
||||
self.plugin = plugin
|
||||
@@ -17,38 +18,38 @@ class AsyncWriter(threading.Thread):
|
||||
self.queue.append(data)
|
||||
|
||||
def ready(self):
|
||||
return len(self.queue)>0
|
||||
return len(self.queue) > 0
|
||||
|
||||
def quit(self):
|
||||
self.quit_flag = True
|
||||
|
||||
def run(self):
|
||||
while not self.quit_flag:
|
||||
#print("AsyncWriter looping..")
|
||||
# print("AsyncWriter looping..")
|
||||
if not self.plugin.active or self.plugin.disabled:
|
||||
#print("plugin active or disabled - exiting!")
|
||||
# print("plugin active or disabled - exiting!")
|
||||
return
|
||||
if self.plugin.ser is None or not self.plugin.ser:
|
||||
#print("no stream - skipping")
|
||||
# print("no stream - skipping")
|
||||
time.sleep(0.5)
|
||||
continue
|
||||
if not self.ready():
|
||||
#print("not ready - skipping")
|
||||
# print("not ready - skipping")
|
||||
time.sleep(0.005)
|
||||
continue
|
||||
item = self.queue.pop(0)
|
||||
if item is not None:
|
||||
#print("sending %s" % item)
|
||||
# print("sending %s" % item)
|
||||
self.plugin.ser.write(item)
|
||||
time.sleep(len(item)*0.005)
|
||||
time.sleep(len(item) * 0.005)
|
||||
else:
|
||||
time.sleep(0.01)
|
||||
if len(self.queue)>4:
|
||||
if len(self.queue) > 4:
|
||||
self.queue = self.queue[-4:4]
|
||||
|
||||
|
||||
class WJSendPlugin(ActionsPlugin, SequencePlugin, DisplayPlugin, ModulationReceiverPlugin, AutomationSourcePlugin):
|
||||
DEBUG = False #True
|
||||
DEBUG = False # True
|
||||
ser = None
|
||||
|
||||
active = True
|
||||
@@ -68,7 +69,7 @@ class WJSendPlugin(ActionsPlugin, SequencePlugin, DisplayPlugin, ModulationRecei
|
||||
rtscts=True, # TODO : test without this one
|
||||
timeout=timeout)"""
|
||||
|
||||
THROTTLE = 20 # milliseconds to wait between refreshing parameters
|
||||
THROTTLE = 20 # milliseconds to wait between refreshing parameters
|
||||
|
||||
selected_command_name = None
|
||||
selected_argument_index = 0
|
||||
@@ -83,24 +84,24 @@ class WJSendPlugin(ActionsPlugin, SequencePlugin, DisplayPlugin, ModulationRecei
|
||||
self.presets = self.load_presets()
|
||||
print("read presets:\n%s\n" % self.presets)
|
||||
# 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()
|
||||
|
||||
# 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.pc.actions.tk.after(500, self.start_plugin)
|
||||
|
||||
self.selected_command_name = list(sorted(self.commands.keys()))[0] # select first command
|
||||
self.selected_command_name = list(sorted(self.commands.keys()))[0] # select first command
|
||||
|
||||
def load_presets(self):
|
||||
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):
|
||||
for cmd,struct in self.commands.items():
|
||||
self.presets.setdefault('modulation_levels',{})[cmd] = struct.get('modulation',[{},{},{},{}])
|
||||
for cmd, struct in self.commands.items():
|
||||
self.presets.setdefault('modulation_levels', {})[cmd] = struct.get('modulation', [{}, {}, {}, {}])
|
||||
self.pc.update_json(self.PRESET_FILE_NAME, self.presets)
|
||||
|
||||
def start_plugin(self):
|
||||
@@ -113,14 +114,14 @@ class WJSendPlugin(ActionsPlugin, SequencePlugin, DisplayPlugin, ModulationRecei
|
||||
self.asyncwriter = None
|
||||
self.save_presets()
|
||||
|
||||
|
||||
# methods/vars for AutomationSourcePlugin
|
||||
# a lot of the nitty-gritty handled in parent class, these are for interfacing to the plugin
|
||||
last_record = {}
|
||||
|
||||
def get_frame_data(self):
|
||||
diff = self.last_record.copy()
|
||||
#self.last_record = {}
|
||||
#print(">>> reporting frame data for rec\n\t%s" % diff)
|
||||
# self.last_record = {}
|
||||
# print(">>> reporting frame data for rec\n\t%s" % diff)
|
||||
return diff
|
||||
|
||||
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)
|
||||
for queue, item in data.items():
|
||||
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):
|
||||
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)
|
||||
# experimental & hardcoded !
|
||||
# TODO: make this not hardcoded and configurable mapping modulation to parameters, preferably on-the-fly..
|
||||
modulation_value = [0.0,0.0,0.0,0.0]
|
||||
modulation_value = [0.0, 0.0, 0.0, 0.0]
|
||||
|
||||
def set_modulation_value(self, param, value):
|
||||
|
||||
self.modulation_value[param] = value ## invert so that no signal always gives a value ..
|
||||
#print("storing modulation slot %s as %s" % (param,value))
|
||||
self.modulation_value[param] = value ## invert so that no signal always gives a value ..
|
||||
# print("storing modulation slot %s as %s" % (param,value))
|
||||
|
||||
# take modulation value and throw it to local parameter
|
||||
if self.DEBUG: print("||||| WJSendPlugin received set_modulation_value for param %s with value %s!" % (param, value))
|
||||
#v = (0.5+value)/2
|
||||
if self.DEBUG:
|
||||
print("||||| WJSendPlugin received set_modulation_value for param %s with value %s!" % (param, value))
|
||||
# v = (0.5+value)/2
|
||||
"""mapped = [
|
||||
'mix',
|
||||
'colour_T',
|
||||
#'colour_T',
|
||||
'back_colour:x'
|
||||
]"""
|
||||
#self.catch_all(*mapped[param].split(":")+[v])
|
||||
#self.commands[
|
||||
# self.catch_all(*mapped[param].split(":")+[v])
|
||||
# self.commands[
|
||||
# find which commands are mapped to this modulation, and trigger a send of them
|
||||
# so that they update with the new modulation value
|
||||
to_send = {}
|
||||
for queue,cmd in sorted(self.command_by_queue.items(),reverse=True):
|
||||
cmd.setdefault('modulation',[{},{},{},{}])
|
||||
for queue, cmd in sorted(self.command_by_queue.items(), reverse=True):
|
||||
cmd.setdefault('modulation', [{}, {}, {}, {}])
|
||||
|
||||
if self.DEBUG: print("\tparam %s, checking modulation %s" % (param, cmd.get('modulation')))
|
||||
if len(cmd['modulation'][param])>0:
|
||||
if self.DEBUG: print("\tParam %s has modulation! sending update of values? %s" %
|
||||
(param, [cmd['arguments'][y] for y in cmd['arg_names'] ]))
|
||||
#self.send_buffered(cmd['queue'], cmd['form'], [x for x in [ cmd['arguments'][y] for y in cmd['arg_names'] ] ], record=False)
|
||||
to_send[cmd['queue']] = cmd
|
||||
continue
|
||||
if self.DEBUG:
|
||||
print("\tparam %s, checking modulation %s" % (param, cmd.get('modulation')))
|
||||
if len(cmd['modulation'][param]) > 0:
|
||||
if self.DEBUG:
|
||||
print("\tParam %s has modulation! sending update of values? %s" %
|
||||
(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
|
||||
continue
|
||||
|
||||
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)
|
||||
#with self.queue_lock:
|
||||
#self.send(cmd['queue'], cmd['form'], [x for x in [ cmd['arguments'][y] for y in cmd['arg_names'] ] ])
|
||||
|
||||
#methods for DisplayPlugin
|
||||
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)
|
||||
# with self.queue_lock:
|
||||
# self.send(cmd['queue'], cmd['form'], [x for x in [ cmd['arguments'][y] for y in cmd['arg_names'] ] ])
|
||||
|
||||
# methods for DisplayPlugin
|
||||
def show_plugin(self, display, display_mode):
|
||||
from tkinter import END
|
||||
display.display_text.insert(END, '{} \n'.format(display.body_title))
|
||||
@@ -186,31 +191,30 @@ class WJSendPlugin(ActionsPlugin, SequencePlugin, DisplayPlugin, ModulationRecei
|
||||
for queue, last in sorted(self.last_modulated.items()):
|
||||
is_selected = queue == self.commands[self.selected_command_name].get('queue')
|
||||
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:
|
||||
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")
|
||||
|
||||
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']:
|
||||
is_selected = cmd['arg_names'].index(arg_name)==self.selected_argument_index
|
||||
output += "\t " #Mod
|
||||
is_selected = cmd['arg_names'].index(arg_name) == self.selected_argument_index
|
||||
output += "\t " # Mod
|
||||
indicator = " " if not is_selected else "["
|
||||
output += "%s%s: "%(indicator,arg_name)
|
||||
for slot,mods in enumerate(cmd.setdefault('modulation',[{},{},{},{}])):
|
||||
#if arg_name in mods:
|
||||
v = mods.get(arg_name,0.0)
|
||||
g = '%s'%self.pc.display.get_bar(v)
|
||||
output += "{}:{}|".format(self.pc.display.get_mod_slot_label(slot),g)
|
||||
output += "%s%s: " % (indicator, arg_name)
|
||||
for slot, mods in enumerate(cmd.setdefault('modulation', [{}, {}, {}, {}])):
|
||||
# if arg_name in mods:
|
||||
v = mods.get(arg_name, 0.0)
|
||||
g = '%s' % self.pc.display.get_bar(v)
|
||||
output += "{}:{}|".format(self.pc.display.get_mod_slot_label(slot), g)
|
||||
if is_selected:
|
||||
output+="]"
|
||||
output += "]"
|
||||
output += "\n"
|
||||
display.display_text.insert(END, output+"\n")
|
||||
display.display_text.insert(END, output + "\n")
|
||||
|
||||
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
|
||||
def open_serial(self, port='/dev/ttyUSB0', baudrate=9600):
|
||||
@@ -220,39 +224,40 @@ class WJSendPlugin(ActionsPlugin, SequencePlugin, DisplayPlugin, ModulationRecei
|
||||
return
|
||||
try:
|
||||
self.ser = serial.Serial(
|
||||
port=port,
|
||||
baudrate=baudrate,
|
||||
bytesize=serial.SEVENBITS,
|
||||
parity=serial.PARITY_ODD,
|
||||
stopbits=serial.STOPBITS_ONE,
|
||||
xonxoff=False,
|
||||
rtscts=True, # TODO : test without this one
|
||||
timeout=None #timeout
|
||||
port=port,
|
||||
baudrate=baudrate,
|
||||
bytesize=serial.SEVENBITS,
|
||||
parity=serial.PARITY_ODD,
|
||||
stopbits=serial.STOPBITS_ONE,
|
||||
xonxoff=False,
|
||||
rtscts=True, # TODO : test without this one
|
||||
timeout=None # timeout
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
print ("WJSendPlugin>> open_serial failed: " + str(type(e)))
|
||||
print("WJSendPlugin>> open_serial failed: " + str(type(e)))
|
||||
self.disabled = True
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
import threading
|
||||
serial_lock = threading.Lock()
|
||||
|
||||
def send_serial_string(self, string):
|
||||
# TODO: thread this so can implement throttling and reduce bottleneck...
|
||||
if not self.active:
|
||||
return
|
||||
try:
|
||||
if self.DEBUG:
|
||||
if self.DEBUG:
|
||||
print("WJSendPlugin>> sending string %s " % string)
|
||||
output = b'\2' + string.encode('ascii') + b'\3'
|
||||
#with self.serial_lock:
|
||||
#self.ser.write(b'\2\2\2\2\3\3\3\3')
|
||||
output = b'\2' + string.encode('ascii') + b'\3'
|
||||
# with self.serial_lock:
|
||||
# self.ser.write(b'\2\2\2\2\3\3\3\3')
|
||||
if self.asyncwriter is None:
|
||||
self.asyncwriter = AsyncWriter(self)
|
||||
self.asyncwriter.start()
|
||||
self.asyncwriter.write(output)
|
||||
#self.ser.write(output) #.encode())
|
||||
# self.ser.write(output) #.encode())
|
||||
# TODO: sleeping here seems to help serial response lag problem?
|
||||
"""self.sleep = 0.2 #self.pc.get_variable('A')
|
||||
#print ("got sleep %s" % self.sleep)
|
||||
@@ -260,17 +265,18 @@ class WJSendPlugin(ActionsPlugin, SequencePlugin, DisplayPlugin, ModulationRecei
|
||||
#print("using sleep %s" % self.sleep)
|
||||
import time
|
||||
time.sleep(self.sleep/10.0)"""
|
||||
#yield from self.ser.drain()
|
||||
if self.DEBUG:
|
||||
print("send_serial_string: sent string '%s'" % output) #.encode('ascii'))
|
||||
#if 'S' in string:
|
||||
# yield from self.ser.drain()
|
||||
if self.DEBUG:
|
||||
print("send_serial_string: sent string '%s'" % output) # .encode('ascii'))
|
||||
# if 'S' in string:
|
||||
# self.get_device_status()
|
||||
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 = {}
|
||||
import threading
|
||||
queue_lock = threading.Lock()
|
||||
|
||||
# send the queued commands to WJMX
|
||||
def refresh(self):
|
||||
if not self.ser or self.ser is None:
|
||||
@@ -279,11 +285,11 @@ class WJSendPlugin(ActionsPlugin, SequencePlugin, DisplayPlugin, ModulationRecei
|
||||
try:
|
||||
# sorting the commands that are sent seems to fix jerk and lag that is otherwise pretty horrendous
|
||||
with self.queue_lock:
|
||||
for queue, command in sorted(self.queue.items()):
|
||||
self.send_buffered(queue, command[0], command[1])
|
||||
#self.queue.clear()
|
||||
for queue, command in sorted(self.queue.items()):
|
||||
self.send_buffered(queue, command[0], command[1])
|
||||
# self.queue.clear()
|
||||
except Exception:
|
||||
print ("WJSendPlugin>>> !!! CAUGHT EXCEPTION running queue %s!!!" % queue)
|
||||
print("WJSendPlugin>>> !!! CAUGHT EXCEPTION running queue %s!!!" % queue)
|
||||
import traceback
|
||||
print(traceback.format_exc())
|
||||
finally:
|
||||
@@ -294,61 +300,62 @@ class WJSendPlugin(ActionsPlugin, SequencePlugin, DisplayPlugin, ModulationRecei
|
||||
self.pc.shaders.root.after(self.THROTTLE, self.refresh)
|
||||
|
||||
def send(self, queue, form, args):
|
||||
#self.send_buffered(queue,output)
|
||||
# self.send_buffered(queue,output)
|
||||
with self.queue_lock:
|
||||
self.queue[queue] = (form, args) #output
|
||||
self.queue[queue] = (form, args) # output
|
||||
|
||||
last = {}
|
||||
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
|
||||
mod_args = self.modulate_arguments(self.command_by_queue.get(queue), 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))
|
||||
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))
|
||||
# TODO: actually output modulated version of args
|
||||
output = form.format(*mod_args)
|
||||
self.send_serial_string(output)
|
||||
else:
|
||||
if self.DEBUG: print("WJSendPlugin>> skipping sending %s %s as it is similar to what was previously sent" % (form,mod_args))
|
||||
if self.DEBUG:
|
||||
print("WJSendPlugin>> skipping sending %s %s as it is similar to what was previously sent" % (form, mod_args))
|
||||
|
||||
self.last[queue] = (form,args)
|
||||
self.last_modulated[queue] = (form,mod_args)
|
||||
if self.last[queue]!=(form,args) and record:
|
||||
self.last_record[queue] = (form,args)
|
||||
self.last[queue] = (form, args)
|
||||
self.last_modulated[queue] = (form, mod_args)
|
||||
if self.last[queue] != (form, args) and record:
|
||||
self.last_record[queue] = (form, args)
|
||||
else:
|
||||
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):
|
||||
# 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):
|
||||
# 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
|
||||
@property
|
||||
def parserlist(self):
|
||||
return [
|
||||
( r"^open_serial$", self.open_serial ),
|
||||
( 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_back_colour:([x|y|z])$", self.set_back_colour ),
|
||||
#( r"^wj_set_position:([N|L])_([x|y])$", self.set_position ),
|
||||
#( 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_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:([:0-9a-zA-Z]*)$", self.send_append ),
|
||||
( r"^wj_set_([a-zA-Z_]*)[:]?([a-zA-Z_]*)$", self.catch_all ),
|
||||
( r"^wj_select_next_command$", self.select_next_command ),
|
||||
( r"^wj_select_previous_command$", self.select_previous_command ),
|
||||
( r"^wj_select_next_argument$", self.select_next_argument ),
|
||||
( r"^wj_select_previous_argument$", self.select_previous_argument ),
|
||||
( r"^wj_reset_modulation$", self.reset_modulation_levels ),
|
||||
( r"^wj_toggle_active$", self.toggle_active )
|
||||
(r"^open_serial$", self.open_serial),
|
||||
(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_back_colour:([x|y|z])$", self.set_back_colour ),
|
||||
# ( r"^wj_set_position:([N|L])_([x|y])$", self.set_position ),
|
||||
# ( 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_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:([:0-9a-zA-Z]*)$", self.send_append),
|
||||
(r"^wj_set_([a-zA-Z_]*)[:]?([a-zA-Z_]*)$", self.catch_all),
|
||||
(r"^wj_select_next_command$", self.select_next_command),
|
||||
(r"^wj_select_previous_command$", self.select_previous_command),
|
||||
(r"^wj_select_next_argument$", self.select_next_argument),
|
||||
(r"^wj_select_previous_argument$", self.select_previous_argument),
|
||||
(r"^wj_reset_modulation$", self.reset_modulation_levels),
|
||||
(r"^wj_toggle_active$", self.toggle_active)
|
||||
]
|
||||
|
||||
def toggle_active(self):
|
||||
@@ -357,29 +364,31 @@ class WJSendPlugin(ActionsPlugin, SequencePlugin, DisplayPlugin, ModulationRecei
|
||||
self.asyncwriter = None
|
||||
|
||||
def reset_modulation_levels(self):
|
||||
for cmd,struct in self.commands.items():
|
||||
struct['modulation'] = [{},{},{},{}]
|
||||
for cmd, struct in self.commands.items():
|
||||
struct['modulation'] = [{}, {}, {}, {}]
|
||||
|
||||
def set_modulation_command_argument_level(self, command_name, argument_name, slot, level):
|
||||
if self.DEBUG: print("set_modulation_command_argument_level(%s, %s, %s, %s)" % (command_name, argument_name, slot, level))
|
||||
if not argument_name: self.commands[command_name]['arg_names'][0] #argument_name = 'v'
|
||||
if self.DEBUG:
|
||||
print("set_modulation_command_argument_level(%s, %s, %s, %s)" % (command_name, argument_name, slot, level))
|
||||
if not argument_name:
|
||||
self.commands[command_name]['arg_names'][0] # argument_name = 'v'
|
||||
|
||||
self.commands[command_name].setdefault('modulation',[{},{},{},{}])[slot][argument_name] = level
|
||||
self.commands[command_name].setdefault('modulation', [{}, {}, {}, {}])[slot][argument_name] = 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)
|
||||
|
||||
def select_previous_command(self):
|
||||
selected_command_index = list(sorted(self.commands.keys())).index(self.selected_command_name)-1
|
||||
if selected_command_index<0:
|
||||
selected_command_index = len(self.commands.keys())-1
|
||||
selected_command_index = list(sorted(self.commands.keys())).index(self.selected_command_name) - 1
|
||||
if selected_command_index < 0:
|
||||
selected_command_index = len(self.commands.keys()) - 1
|
||||
self.selected_command_name = sorted(list(self.commands.keys()))[selected_command_index]
|
||||
|
||||
self.selected_argument_index = 0
|
||||
|
||||
def select_next_command(self):
|
||||
selected_command_index = list(sorted(self.commands.keys())).index(self.selected_command_name)+1
|
||||
if selected_command_index>=len(self.commands.keys()):
|
||||
selected_command_index = list(sorted(self.commands.keys())).index(self.selected_command_name) + 1
|
||||
if selected_command_index >= len(self.commands.keys()):
|
||||
selected_command_index = 0
|
||||
self.selected_command_name = sorted(list(self.commands.keys()))[selected_command_index]
|
||||
|
||||
@@ -387,91 +396,94 @@ class WJSendPlugin(ActionsPlugin, SequencePlugin, DisplayPlugin, ModulationRecei
|
||||
|
||||
def select_previous_argument(self):
|
||||
self.selected_argument_index -= 1
|
||||
if self.selected_argument_index<0:
|
||||
self.selected_argument_index = len(self.commands[self.selected_command_name]['arg_names'])-1
|
||||
if self.selected_argument_index < 0:
|
||||
self.selected_argument_index = len(self.commands[self.selected_command_name]['arg_names']) - 1
|
||||
|
||||
def select_next_argument(self):
|
||||
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
|
||||
|
||||
def catch_all(self, param, argument_name, value):
|
||||
#print ("got catch-all %s, %s, %s" % (param, argument_name, value))
|
||||
#arguments = packed_arguments.split("_") + [ value ]
|
||||
#print("commands looks like %s" % self.commands)
|
||||
# print ("got catch-all %s, %s, %s" % (param, argument_name, value))
|
||||
# arguments = packed_arguments.split("_") + [ value ]
|
||||
# print("commands looks like %s" % self.commands)
|
||||
msg = self.commands[param]
|
||||
if len(msg['arg_names'])==1: argument_name = msg['arg_names'][0]
|
||||
msg['arguments'][argument_name] = int(value*255) # = arguments
|
||||
self.send(msg['queue'], msg['form'], [ msg['arguments'][p] for p in msg['arg_names'] ] )
|
||||
if len(msg['arg_names']) == 1:
|
||||
argument_name = msg['arg_names'][0]
|
||||
msg['arguments'][argument_name] = int(value * 255) # = arguments
|
||||
self.send(msg['queue'], msg['form'], [msg['arguments'][p] for p in msg['arg_names']])
|
||||
|
||||
def modulate_arguments(self, command, args):
|
||||
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
|
||||
for slot in range(0,4):
|
||||
modlevels = command.get('modulation',[{},{},{},{}])[slot]
|
||||
#if self.DEBUG: print("\tfor modulate_arguments for slot %s got modlevels: %s" % (slot, modlevels))
|
||||
#for i,m in enumerate(modlevels.values()):
|
||||
for arg_name,m in modlevels.items():
|
||||
if m>0.0:
|
||||
for slot in range(0, 4):
|
||||
modlevels = command.get('modulation', [{}, {}, {}, {}])[slot]
|
||||
# if self.DEBUG: print("\tfor modulate_arguments for slot %s got modlevels: %s" % (slot, modlevels))
|
||||
# for i,m in enumerate(modlevels.values()):
|
||||
for arg_name, m in modlevels.items():
|
||||
if m > 0.0:
|
||||
arg_index = command.get('arg_names').index(arg_name)
|
||||
if self.DEBUG: print("\t\tupdating modulation slot %s, arg is %s\n\t with modlevel '%s' * modvalue '%s'" % (arg_index, args[arg_index], m, self.modulation_value[slot]))
|
||||
if self.DEBUG:
|
||||
print("\t\tupdating modulation slot %s, arg is %s\n\t with modlevel '%s' * modvalue '%s'" % (arg_index, args[arg_index], m, self.modulation_value[slot]))
|
||||
# amount, value, level
|
||||
newvalue = self.pc.shaders.get_modulation_value(
|
||||
args[arg_index]/255.0,
|
||||
self.modulation_value[slot],
|
||||
args[arg_index] / 255.0,
|
||||
self.modulation_value[slot],
|
||||
m
|
||||
)
|
||||
if self.DEBUG: print("\t\tnewvalue is %s" %newvalue)
|
||||
args[arg_index] = int(255*newvalue)
|
||||
if self.DEBUG: print("modulate_arguments returning:\n\t%s" % args)
|
||||
if self.DEBUG:
|
||||
print("\t\tnewvalue is %s" % newvalue)
|
||||
args[arg_index] = int(255 * newvalue)
|
||||
if self.DEBUG:
|
||||
print("modulate_arguments returning:\n\t%s" % args)
|
||||
return args
|
||||
|
||||
# panasonic parameters are 8 bit so go 0-255, so 127 is default of centre value
|
||||
commands = {
|
||||
'colour_gain_T': {
|
||||
'name': 'Colour Corrector gain (both)',
|
||||
'queue': 'VCG',
|
||||
'form': 'VCG:T{:02X}',
|
||||
'arg_names': [ 'v' ],
|
||||
'arguments': { 'v': 127 }
|
||||
},
|
||||
'colour_T': {
|
||||
'name': 'Colour Corrector (both)',
|
||||
'queue': 'VCC',
|
||||
'form': 'VCC:T{:02X}{:02X}',
|
||||
'arg_names': [ 'x', 'y' ],
|
||||
'arguments': { 'x': 127, 'y': 127 },
|
||||
},
|
||||
'mix': {
|
||||
'name': 'Mix/wipe',
|
||||
'queue': 'VMM',
|
||||
'form': 'VMM:{:02X}',
|
||||
'arg_names': [ 'v' ],
|
||||
'arguments': { 'v': 127 },
|
||||
},
|
||||
'back_colour': {
|
||||
'name': 'Matte colour HSV',
|
||||
'queue': 'VBM',
|
||||
'form': 'VBM:{:02X}{:02X}{:02X}',
|
||||
'arg_names': [ 'h', 's', 'v' ],
|
||||
'arguments': { 'h': 127, 's': 127, 'v': 127 },
|
||||
},
|
||||
'position_N': {
|
||||
'name': 'Positioner joystick XY',
|
||||
'queue': 'VPS',
|
||||
'form': 'VPS:N{:02X}{:02X}',
|
||||
'arg_names': [ 'y', 'x' ],
|
||||
'arguments': { 'y': 127, 'x': 127 }
|
||||
},
|
||||
#'dsk_slice': { ## cant seem to find the right control code for this?!
|
||||
# 'name': 'Downstream Key Slice,Slope',
|
||||
# 'queue': 'VDS',
|
||||
# 'form': 'VDS:{:02X}{:01X}',
|
||||
# 'arg_names': [ 'slice','slope' ],
|
||||
# 'arguments': { 'slice': 127, 'slope': 8 },
|
||||
# 'modulation': [ {}, { 'slice': 1.0 }, {}, {} ]
|
||||
#}
|
||||
'colour_gain_T': {
|
||||
'name': 'Colour Corrector gain (both)',
|
||||
'queue': 'VCG',
|
||||
'form': 'VCG:T{:02X}',
|
||||
'arg_names': ['v'],
|
||||
'arguments': {'v': 127}
|
||||
},
|
||||
'colour_T': {
|
||||
'name': 'Colour Corrector (both)',
|
||||
'queue': 'VCC',
|
||||
'form': 'VCC:T{:02X}{:02X}',
|
||||
'arg_names': ['x', 'y'],
|
||||
'arguments': {'x': 127, 'y': 127},
|
||||
},
|
||||
'mix': {
|
||||
'name': 'Mix/wipe',
|
||||
'queue': 'VMM',
|
||||
'form': 'VMM:{:02X}',
|
||||
'arg_names': ['v'],
|
||||
'arguments': {'v': 127},
|
||||
},
|
||||
'back_colour': {
|
||||
'name': 'Matte colour HSV',
|
||||
'queue': 'VBM',
|
||||
'form': 'VBM:{:02X}{:02X}{:02X}',
|
||||
'arg_names': ['h', 's', 'v'],
|
||||
'arguments': {'h': 127, 's': 127, 'v': 127},
|
||||
},
|
||||
'position_N': {
|
||||
'name': 'Positioner joystick XY',
|
||||
'queue': 'VPS',
|
||||
'form': 'VPS:N{:02X}{:02X}',
|
||||
'arg_names': ['y', 'x'],
|
||||
'arguments': {'y': 127, 'x': 127}
|
||||
},
|
||||
# 'dsk_slice': { ## cant seem to find the right control code for this?!
|
||||
# 'name': 'Downstream Key Slice,Slope',
|
||||
# 'queue': 'VDS',
|
||||
# 'form': 'VDS:{:02X}{:01X}',
|
||||
# 'arg_names': [ 'slice','slope' ],
|
||||
# 'arguments': { 'slice': 127, 'slope': 8 },
|
||||
# 'modulation': [ {}, { 'slice': 1.0 }, {}, {} ]
|
||||
# }
|
||||
}
|
||||
command_by_queue = {}
|
||||
|
||||
|
||||
@@ -1,55 +1,59 @@
|
||||
import copy
|
||||
from json import JSONEncoder
|
||||
|
||||
|
||||
def _default(self, obj):
|
||||
if getattr(obj.__class__,'to_json'):
|
||||
#return _default.default(obj.to_json())
|
||||
if getattr(obj.__class__, 'to_json'):
|
||||
# return _default.default(obj.to_json())
|
||||
return obj.to_json()
|
||||
else:
|
||||
return _default.default(obj)
|
||||
|
||||
|
||||
_default.default = JSONEncoder().default
|
||||
JSONEncoder.default = _default
|
||||
|
||||
|
||||
class Frame:
|
||||
f = { 'shader_params': [[None]*4,[None]*4,[None]*4] }
|
||||
f = {'shader_params': [[None] * 4, [None] * 4, [None] * 4]}
|
||||
pc = None
|
||||
|
||||
DEBUG_FRAMES = False#True
|
||||
DEBUG_FRAMES = False # True
|
||||
|
||||
def __init__(self, pc):
|
||||
self.pc = pc
|
||||
|
||||
def to_json(self):
|
||||
return self.f #{ 'f': self.f }
|
||||
return self.f # { 'f': self.f }
|
||||
|
||||
def get(self, key, default=None):
|
||||
return self.f.get(key,default)
|
||||
return self.f.get(key, default)
|
||||
|
||||
def has(self, key):
|
||||
return self.get(key) is not None
|
||||
|
||||
def store_live(self):
|
||||
frame = {
|
||||
#'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),
|
||||
'shader_params': copy.deepcopy(self.pc.shaders.selected_param_list),
|
||||
'layer_active_status': copy.deepcopy(self.pc.shaders.selected_status_list),
|
||||
'feedback_active': self.pc.shaders.data.feedback_active,
|
||||
'x3_as_speed': self.pc.shaders.data.settings['shader']['X3_AS_SPEED']['value'],
|
||||
'shader_speeds': copy.deepcopy(self.pc.shaders.selected_speed_list),
|
||||
'strobe_amount': self.pc.shaders.data.settings['shader']['STROBE_AMOUNT']['value'] / 10.0,
|
||||
'shader_modulation_levels': copy.deepcopy(self.pc.shaders.modulation_level)
|
||||
# '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),
|
||||
'shader_params': copy.deepcopy(self.pc.shaders.selected_param_list),
|
||||
'layer_active_status': copy.deepcopy(self.pc.shaders.selected_status_list),
|
||||
'feedback_active': self.pc.shaders.data.feedback_active,
|
||||
'x3_as_speed': self.pc.shaders.data.settings['shader']['X3_AS_SPEED']['value'],
|
||||
'shader_speeds': copy.deepcopy(self.pc.shaders.selected_speed_list),
|
||||
'strobe_amount': self.pc.shaders.data.settings['shader']['STROBE_AMOUNT']['value'] / 10.0,
|
||||
'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())
|
||||
self.f = frame
|
||||
#print("built frame: %s" % self.f)
|
||||
# print("built frame: %s" % self.f)
|
||||
return self
|
||||
|
||||
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.get('f') is not None: #isinstance(f, Frame):
|
||||
if f.get('f') is not None: # isinstance(f, Frame):
|
||||
f = f.get('f')
|
||||
return self.store_copy(f.get('f'))
|
||||
self.f = f
|
||||
@@ -60,12 +64,12 @@ class Frame:
|
||||
def get_active_shader_names(self):
|
||||
s = ""
|
||||
if self.has('selected_shader_slots'):
|
||||
return ['-']*3
|
||||
return ['-'] * 3
|
||||
if self.has('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 '-'\
|
||||
for layer,x in enumerate(self.get('selected_shader_slots',[None]*3))
|
||||
]
|
||||
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 '-' \
|
||||
for layer, x in enumerate(self.get('selected_shader_slots', [None] * 3))
|
||||
]
|
||||
|
||||
def get_frame_summary(self):
|
||||
summary = []
|
||||
@@ -73,30 +77,30 @@ class Frame:
|
||||
|
||||
# list the recorded shader info in compact format
|
||||
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)
|
||||
summary.append(s)
|
||||
|
||||
|
||||
# handle summarising the rest of the recorded shader info, two-to-a-line where possible
|
||||
count = 0
|
||||
line = ""
|
||||
for key,d in sorted(self.f.items()):
|
||||
#print ("get_frame_summary: checking %s value %s" % (key,d))
|
||||
if type(d) is dict and len(d)==0: # skip empty dicts
|
||||
for key, d in sorted(self.f.items()):
|
||||
# print ("get_frame_summary: checking %s value %s" % (key,d))
|
||||
if type(d) is dict and len(d) == 0: # skip empty dicts
|
||||
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
|
||||
pass
|
||||
elif key in ['shader_modulation_levels']:
|
||||
for layer in range(3):
|
||||
o = ""
|
||||
for slot in range(4):
|
||||
sl = self.pc.display.get_mod_slot_label(slot)
|
||||
o+= sl + "["
|
||||
for param in range(4):
|
||||
o += self.pc.display.get_bar(d[layer][param][slot])
|
||||
o+= "] "
|
||||
summary.append("Shader layer %s: %s"%(layer,o))
|
||||
o = ""
|
||||
for slot in range(4):
|
||||
sl = self.pc.display.get_mod_slot_label(slot)
|
||||
o += sl + "["
|
||||
for param in range(4):
|
||||
o += self.pc.display.get_bar(d[layer][param][slot])
|
||||
o += "] "
|
||||
summary.append("Shader layer %s: %s" % (layer, o))
|
||||
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))
|
||||
"""elif key in ["WJSendPlugin"]:
|
||||
@@ -105,44 +109,42 @@ class Frame:
|
||||
else:
|
||||
line += "%s: %s" % (key, d)
|
||||
count += 1
|
||||
if count%2==1:
|
||||
if count % 2 == 1:
|
||||
line += "\t"
|
||||
elif count>0 and count%2==0:
|
||||
elif count > 0 and count % 2 == 0:
|
||||
summary.append(line)
|
||||
line = ""
|
||||
if line != "":
|
||||
summary.append(line)
|
||||
|
||||
# add 'not shown' items
|
||||
if len(not_shown)>0:
|
||||
if len(not_shown) > 0:
|
||||
summary.append(','.join(not_shown.keys()))
|
||||
|
||||
return summary
|
||||
|
||||
def get_shader_layer_summary(self, layer):
|
||||
s = "%s%s" % (layer, " " if layer != self.pc.data.shader_layer else ">")
|
||||
s += "["
|
||||
s += self.pc.display.get_compact_indicators([\
|
||||
(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'])\
|
||||
for i in range(10)\
|
||||
])
|
||||
s += "]"
|
||||
s = "%s%s" % (layer, " " if layer != self.pc.data.shader_layer else ">")
|
||||
s += "["
|
||||
s += self.pc.display.get_compact_indicators([ \
|
||||
(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']) \
|
||||
for i in range(10) \
|
||||
])
|
||||
s += "]"
|
||||
|
||||
if self.has('layer_active_status'):
|
||||
s += " %s " % (self.get('layer_active_status',['-']*3)[layer])
|
||||
if self.has('layer_active_status'):
|
||||
s += " %s " % (self.get('layer_active_status', ['-'] * 3)[layer])
|
||||
|
||||
if self.get('selected_shader'):
|
||||
s += "{:14.14}".format(self.get('selected_shader')[layer].get('name').replace('.frag','').strip())
|
||||
if self.get('selected_shader'):
|
||||
s += "{:14.14}".format(self.get('selected_shader')[layer].get('name').replace('.frag', '').strip())
|
||||
|
||||
s += " " + self.get_shader_param_summary(layer) + " "
|
||||
|
||||
if self.has('shader_speeds'):
|
||||
s += self.pc.display.get_speed_indicator(self.get('shader_speeds',[0.0]*3)[layer])
|
||||
|
||||
return s
|
||||
s += " " + self.get_shader_param_summary(layer) + " "
|
||||
|
||||
if self.has('shader_speeds'):
|
||||
s += self.pc.display.get_speed_indicator(self.get('shader_speeds', [0.0] * 3)[layer])
|
||||
|
||||
return s
|
||||
|
||||
def get_shader_param_summary(self, layer):
|
||||
if self.get('shader_params') is None:
|
||||
@@ -164,17 +166,17 @@ class Frame:
|
||||
self.recall_frame_params()
|
||||
|
||||
for layer in range(3):
|
||||
if preset.has('selected_shader_slots'): # deprecated/compatibility
|
||||
if preset.has('selected_shader_slots'): # deprecated/compatibility
|
||||
self.pc.actions.call_method_name('play_shader_%s_%s' % (layer, preset.get('selected_shader_slots')[layer]))
|
||||
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
|
||||
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']:
|
||||
self.pc.actions.call_method_name('play_shader_%s_%s' % (layer, slot))
|
||||
found = True
|
||||
break
|
||||
if not found: # otherwise fall back to loading it separately
|
||||
if not found: # otherwise fall back to loading it separately
|
||||
self.pc.shaders.selected_shader_list[self.pc.data.shader_layer] = preset.get('selected_shader')[layer].copy()
|
||||
self.pc.shaders.load_selected_shader()
|
||||
|
||||
@@ -185,40 +187,40 @@ class Frame:
|
||||
level = preset.get('shader_modulation_levels')[layer][param][slot]
|
||||
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))
|
||||
if active=='▶':
|
||||
if active == '▶':
|
||||
self.pc.actions.call_method_name('start_shader_layer_%s' % layer)
|
||||
else:
|
||||
self.pc.actions.call_method_name('stop_shader_layer_%s' % layer)
|
||||
|
||||
def recall_frame_params(self):
|
||||
#print("recall_frame_params got: %s" % preset.get('shader_params'))
|
||||
for (layer, param_list) in enumerate(self.get('shader_params',[])):
|
||||
# print("recall_frame_params got: %s" % preset.get('shader_params'))
|
||||
for (layer, param_list) in enumerate(self.get('shader_params', [])):
|
||||
if param_list:
|
||||
for param,value in enumerate(param_list):
|
||||
#if (ignored is not None and ignored['shader_params'][layer][param] is not None):
|
||||
for param, value in enumerate(param_list):
|
||||
# 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]))
|
||||
# continue
|
||||
if (value is not None):
|
||||
#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)
|
||||
# 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)
|
||||
|
||||
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:
|
||||
self.pc.actions.call_method_name('enable_feedback')
|
||||
else:
|
||||
self.pc.actions.call_method_name('disable_feedback')
|
||||
|
||||
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']:
|
||||
self.data.plugins.actions.call_method_name('enable_x3_as_speed')
|
||||
else:
|
||||
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:
|
||||
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
|
||||
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))
|
||||
|
||||
def merge(self, frame2):
|
||||
from copy import deepcopy
|
||||
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 frame2\t%s" % frame2)
|
||||
for i,f2 in enumerate(frame2.get('shader_params')):
|
||||
for i2,p in enumerate(f2):
|
||||
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 frame2\t%s" % frame2)
|
||||
for i, f2 in enumerate(frame2.get('shader_params')):
|
||||
for i2, p in enumerate(f2):
|
||||
if p is not None:
|
||||
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
|
||||
|
||||
if frame2.has('feedback_active'):
|
||||
@@ -252,7 +254,7 @@ class Frame:
|
||||
if 'shader_speeds' in frame2.f:
|
||||
f['shader_speeds'] = frame2.get('shader_speeds')
|
||||
else:
|
||||
for i,s in enumerate(frame2.get('shader_speeds')):
|
||||
for i, s in enumerate(frame2.get('shader_speeds')):
|
||||
if s is not None:
|
||||
f['shader_speeds'][i] = s
|
||||
|
||||
@@ -261,19 +263,21 @@ class Frame:
|
||||
|
||||
from data_centre.plugin_collection import 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)
|
||||
|
||||
|
||||
def get_ignored(self, ignored):
|
||||
from copy import deepcopy
|
||||
f = deepcopy(self.f) #frame1.copy()
|
||||
f = deepcopy(self.f) # frame1.copy()
|
||||
frame = self.f
|
||||
ignored = ignored.f
|
||||
if self.DEBUG_FRAMES: print("get_frame_ignored: got frame\t%s" % self.f)
|
||||
for i,f2 in enumerate(frame.get('shader_params',[])):
|
||||
for i2,p in enumerate(f2):
|
||||
if self.DEBUG_FRAMES:
|
||||
print("get_frame_ignored: got frame\t%s" % self.f)
|
||||
for i, f2 in enumerate(frame.get('shader_params', [])):
|
||||
for i2, p in enumerate(f2):
|
||||
if ignored['shader_params'][i][i2] is not None:
|
||||
f['shader_params'][i][i2] = None
|
||||
if 'feedback_active' in ignored:
|
||||
@@ -281,26 +285,28 @@ class Frame:
|
||||
if 'x3_as_speed' in ignored:
|
||||
f['x3_as_speed'] = None
|
||||
if 'shader_speeds' in ignored and 'shader_speeds' in frame:
|
||||
for i,s in enumerate(frame.get('shader_speeds')):
|
||||
if ignored['shader_speeds'][i] is not None:
|
||||
f['shader_speeds'][i] = None
|
||||
for i, s in enumerate(frame.get('shader_speeds')):
|
||||
if ignored['shader_speeds'][i] is not None:
|
||||
f['shader_speeds'][i] = None
|
||||
if 'strobe_amount' in ignored:
|
||||
f['strobe_amount'] = None
|
||||
|
||||
from data_centre.plugin_collection import AutomationSourcePlugin
|
||||
for plugin in self.pc.get_plugins(AutomationSourcePlugin):
|
||||
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)))
|
||||
f[plugin.frame_key] = plugin.get_ignored_data(f.get(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, {}))
|
||||
|
||||
if self.DEBUG_FRAMES: print("get_frame_ignored: got return\t%s" % f)
|
||||
if self.DEBUG_FRAMES:
|
||||
print("get_frame_ignored: got return\t%s" % f)
|
||||
return Frame(self.pc).store_copy(f)
|
||||
|
||||
def is_empty(self):
|
||||
#from copy import deepcopy
|
||||
#f = deepcopy(frame) #frame1.copy()
|
||||
# from copy import deepcopy
|
||||
# f = deepcopy(frame) #frame1.copy()
|
||||
frame = self.f
|
||||
if self.DEBUG_FRAMES: print("is_frame_empty: got frame\t%s" % frame)
|
||||
if self.DEBUG_FRAMES:
|
||||
print("is_frame_empty: got frame\t%s" % frame)
|
||||
|
||||
if self.has('feedback_active'):
|
||||
return False
|
||||
@@ -309,15 +315,15 @@ class Frame:
|
||||
if self.has('strobe_amount'):
|
||||
return False
|
||||
|
||||
for i,f in enumerate(frame['shader_params']):
|
||||
for i2,p in enumerate(f):
|
||||
if p is not None: #ignored['shader_params'][i][i2] is not None:
|
||||
for i, f in enumerate(frame['shader_params']):
|
||||
for i2, p in enumerate(f):
|
||||
if p is not None: # ignored['shader_params'][i][i2] is not None:
|
||||
return False
|
||||
|
||||
if self.has('shader_speeds'):
|
||||
for i,f in enumerate(frame['shader_speeds']):
|
||||
if f is not None:
|
||||
return False
|
||||
for i, f in enumerate(frame['shader_speeds']):
|
||||
if f is not None:
|
||||
return False
|
||||
|
||||
from data_centre.plugin_collection import AutomationSourcePlugin
|
||||
for plugin in self.pc.get_plugins(AutomationSourcePlugin):
|
||||
@@ -326,11 +332,12 @@ class Frame:
|
||||
if not plugin.is_frame_data_empty(frame.get(plugin.frame_key)):
|
||||
return False
|
||||
|
||||
if self.DEBUG_FRAMES: print("is_frame_empty: got return true")
|
||||
if self.DEBUG_FRAMES:
|
||||
print("is_frame_empty: got return true")
|
||||
return True
|
||||
|
||||
def get_diff(self, current_frame):
|
||||
#if not last_frame: return current_frame
|
||||
# if not last_frame: return current_frame
|
||||
current_frame = current_frame.f
|
||||
last_frame = self.f
|
||||
|
||||
@@ -339,12 +346,13 @@ class Frame:
|
||||
print("last_frame: \t%s" % last_frame['shader_params'])
|
||||
print("current_frame: \t%s" % current_frame['shader_params'])
|
||||
|
||||
param_values = [[None]*4,[None]*4,[None]*4]
|
||||
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))
|
||||
for param,p in enumerate(params):
|
||||
param_values = [[None] * 4, [None] * 4, [None] * 4]
|
||||
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))
|
||||
for param, p in enumerate(params):
|
||||
if p is not None and p != last_frame.get('shader_params')[layer][param]:
|
||||
if self.DEBUG_FRAMES: print("setting layer %s param %s to %s" % (layer,param,p))
|
||||
if self.DEBUG_FRAMES:
|
||||
print("setting layer %s param %s to %s" % (layer, param, p))
|
||||
param_values[layer][param] = p
|
||||
|
||||
if current_frame['feedback_active'] is not None and last_frame['feedback_active'] != current_frame['feedback_active']:
|
||||
@@ -357,8 +365,8 @@ class Frame:
|
||||
else:
|
||||
x3_as_speed = None
|
||||
|
||||
speed_values = [None]*3
|
||||
for layer,param in enumerate(current_frame.get('shader_speeds',[None]*3)):
|
||||
speed_values = [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]:
|
||||
speed_values[layer] = param
|
||||
|
||||
@@ -378,21 +386,19 @@ class Frame:
|
||||
plugin_data[plugin.frame_key] = plugin.get_frame_diff(last_frame, current_frame)
|
||||
|
||||
diff = {
|
||||
'shader_params': param_values,
|
||||
'feedback_active': feedback_active,
|
||||
'x3_as_speed': x3_as_speed,
|
||||
'shader_speeds': speed_values,
|
||||
'strobe_amount': strobe_amount,
|
||||
'shader_params': param_values,
|
||||
'feedback_active': feedback_active,
|
||||
'x3_as_speed': x3_as_speed,
|
||||
'shader_speeds': speed_values,
|
||||
'strobe_amount': strobe_amount,
|
||||
}
|
||||
diff.update(plugin_data)
|
||||
if self.DEBUG_FRAMES: print("returning\t%s\n^^^^" % diff['shader_params'])
|
||||
if self.DEBUG_FRAMES:
|
||||
print("returning\t%s\n^^^^" % diff['shader_params'])
|
||||
|
||||
return Frame(self.pc).store_copy(diff)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class FrameManager:
|
||||
pc = None
|
||||
|
||||
@@ -430,9 +436,9 @@ class FrameManager:
|
||||
from data_centre.plugin_collection import AutomationSourcePlugin
|
||||
for plugin in self.pc.get_plugins(AutomationSourcePlugin):
|
||||
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
|
||||
|
||||
def interpolate_clip(self, frames):
|
||||
@@ -444,9 +450,9 @@ class FrameManager:
|
||||
# else,
|
||||
# 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):
|
||||
if frame is None:
|
||||
@@ -455,18 +461,18 @@ class FrameManager:
|
||||
reproc_to = 0
|
||||
|
||||
def process(self, findex, frame):
|
||||
for layer,params in enumerate(frame.get('shader_params',[])):
|
||||
for param,value in enumerate(params):
|
||||
for layer, params in enumerate(frame.get('shader_params', [])):
|
||||
for param, value in enumerate(params):
|
||||
if value is None and last[layer][param] is not None:
|
||||
# find distance to when this value changes again
|
||||
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
|
||||
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
|
||||
continue
|
||||
newvalue = self.interpolate(last[layer][param], future_value, gap)
|
||||
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))
|
||||
last[layer][param] = newvalue
|
||||
#elif last[layer][param] is None:
|
||||
# elif last[layer][param] is None:
|
||||
# reproc_to = findex
|
||||
elif value is not None:
|
||||
last[layer][param] = value
|
||||
@@ -474,13 +480,13 @@ class FrameManager:
|
||||
from data_centre.plugin_collection import AutomationSourcePlugin
|
||||
for plugin in self.pc.get_plugins(AutomationSourcePlugin):
|
||||
plugin.process_interpolate_clip(frames)
|
||||
|
||||
for i in range(2):
|
||||
for findex,frame in enumerate(frames):
|
||||
if frame is None:
|
||||
continue
|
||||
|
||||
process(self,findex,frame)
|
||||
for i in range(2):
|
||||
for findex, frame in enumerate(frames):
|
||||
if frame is None:
|
||||
continue
|
||||
|
||||
process(self, findex, frame)
|
||||
|
||||
"""for findex in range(reproc_to):
|
||||
if frames[findex] is None:
|
||||
@@ -488,23 +494,23 @@ class FrameManager:
|
||||
|
||||
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):
|
||||
for i in range(1,len(frames)):
|
||||
for i in range(1, len(frames)):
|
||||
search_findex = i + findex
|
||||
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 0, None
|
||||
|
||||
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
|
||||
if value1>value2:
|
||||
v = value1-sl
|
||||
if value1 > value2:
|
||||
v = value1 - sl
|
||||
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
|
||||
|
||||
@@ -29,6 +29,7 @@ message_handler = MessageHandler()
|
||||
|
||||
data = Data(message_handler)
|
||||
|
||||
|
||||
def setup_osc_client():
|
||||
client_parser = argparse.ArgumentParser()
|
||||
client_parser.add_argument("--ip", default="127.0.0.1", help="the ip")
|
||||
@@ -38,10 +39,11 @@ def setup_osc_client():
|
||||
|
||||
return udp_client.SimpleUDPClient(client_args.ip, client_args.port)
|
||||
|
||||
|
||||
osc_client = setup_osc_client()
|
||||
# setup the video driver
|
||||
video_driver = VideoDriver(tk, osc_client, message_handler, data)
|
||||
#capture = Capture(tk, osc_client, message_handler, data)
|
||||
# capture = Capture(tk, osc_client, message_handler, data)
|
||||
shaders = Shaders(tk, osc_client, message_handler, data)
|
||||
|
||||
# setup the display
|
||||
@@ -67,14 +69,12 @@ actions.toggle_x_autorepeat()
|
||||
frame.pack()
|
||||
tk.attributes("-fullscreen", True)
|
||||
|
||||
|
||||
def handle_error(exc, val, tb):
|
||||
print('traceback for error : {}'.format(traceback.format_exc()))
|
||||
message_handler.set_message('ERROR', val, traceback.format_exc())
|
||||
|
||||
|
||||
|
||||
tk.report_callback_exception = handle_error
|
||||
|
||||
|
||||
tk.mainloop()
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import Adafruit_MCP3008
|
||||
|
||||
|
||||
class AnalogInput(object):
|
||||
def __init__(self, root, message_handler, display, actions, data):
|
||||
self.root = root
|
||||
@@ -9,23 +10,22 @@ class AnalogInput(object):
|
||||
self.data = data
|
||||
self.analog_mappings = data.analog_mappings
|
||||
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.check_if_listening_enabled()
|
||||
|
||||
|
||||
def check_if_listening_enabled(self):
|
||||
if self.data.settings['user_input']['ANALOG_INPUT']['value'] == 'enabled':
|
||||
if not self.analog_input:
|
||||
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
|
||||
#SPI_PORT = 1
|
||||
#SPI_DEVICE = 2
|
||||
#self.analog_input = Adafruit_MCP3008.MCP3008(spi=SPI.SpiDev(SPI_PORT, SPI_DEVICE))
|
||||
CLK = 21
|
||||
# SPI_PORT = 1
|
||||
# SPI_DEVICE = 2
|
||||
# self.analog_input = Adafruit_MCP3008.MCP3008(spi=SPI.SpiDev(SPI_PORT, SPI_DEVICE))
|
||||
CLK = 21
|
||||
MISO = 19
|
||||
MOSI = 20
|
||||
CS = 16
|
||||
CS = 16
|
||||
self.analog_input = Adafruit_MCP3008.MCP3008(clk=CLK, cs=CS, miso=MISO, mosi=MOSI)
|
||||
|
||||
except:
|
||||
@@ -37,12 +37,12 @@ class AnalogInput(object):
|
||||
def poll_analog_inputs(self):
|
||||
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:
|
||||
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:
|
||||
#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.last_readings[i] = this_reading
|
||||
self.root.after(self.analog_delay, self.poll_analog_inputs)
|
||||
@@ -69,14 +69,12 @@ class AnalogInput(object):
|
||||
method_name = this_mapping[mode][0]
|
||||
|
||||
if channel_value is not None:
|
||||
norm_channel_value = channel_value/1023
|
||||
norm_channel_value = channel_value / 1023
|
||||
else:
|
||||
norm_channel_value = None
|
||||
|
||||
print('the action being called is {}'.format(method_name))
|
||||
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 ...
|
||||
#if 'cc' not in message_name:
|
||||
# self.display.refresh_display()
|
||||
|
||||
|
||||
# if 'cc' not in message_name:
|
||||
# self.display.refresh_display()
|
||||
|
||||
@@ -18,10 +18,10 @@ class MidiInput(object):
|
||||
self.try_open_port()
|
||||
|
||||
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.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':
|
||||
self.actions.stop_serial_port_process()
|
||||
self.open_this_port_and_start_listening('20')
|
||||
@@ -29,7 +29,7 @@ class MidiInput(object):
|
||||
self.actions.create_serial_port_process()
|
||||
self.open_this_port_and_start_listening('serial')
|
||||
else:
|
||||
self.actions.stop_serial_port_process()
|
||||
self.actions.stop_serial_port_process()
|
||||
self.data.midi_status = 'disconnected'
|
||||
self.root.after(1000, self.try_open_port)
|
||||
|
||||
@@ -40,7 +40,7 @@ class MidiInput(object):
|
||||
midi_devices = [s for s in midi_devices if port_phrase in s]
|
||||
if midi_devices:
|
||||
if self.data.midi_status == 'disconnected':
|
||||
subport_index = self.port_index % len(midi_devices)
|
||||
subport_index = self.port_index % len(midi_devices)
|
||||
self.midi_device = mido.open_input(midi_devices[subport_index])
|
||||
self.data.midi_status = 'connected'
|
||||
self.data.midi_device_name = self.midi_device.name
|
||||
@@ -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_output = self.find_output_plugin(midi_devices[subport_index])
|
||||
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.poll_midi_input()
|
||||
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()]
|
||||
|
||||
refined_buffer = []
|
||||
#refine buffer from lastest messages first
|
||||
# refine buffer from lastest messages first
|
||||
current_message_buffer.reverse()
|
||||
for message in current_message_buffer:
|
||||
# discard notes from wrong channel
|
||||
@@ -81,7 +81,7 @@ class MidiInput(object):
|
||||
for message in refined_buffer:
|
||||
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:
|
||||
self.root.after(self.midi_delay, self.poll_midi_input)
|
||||
else:
|
||||
@@ -94,9 +94,9 @@ class MidiInput(object):
|
||||
mapped_message_name = message_dict['type']
|
||||
mapped_message_value = None
|
||||
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:
|
||||
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']
|
||||
|
||||
if mapped_message_name in self.midi_mappings.keys():
|
||||
@@ -119,23 +119,23 @@ class MidiInput(object):
|
||||
|
||||
if self.data.function_on and len(this_mapping[mode]) > 1:
|
||||
method_name = this_mapping[mode][1]
|
||||
#self.data.function_on = False
|
||||
# self.data.function_on = False
|
||||
else:
|
||||
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))
|
||||
if mapped_message_value is not None:
|
||||
norm_message_value = mapped_message_value/127
|
||||
|
||||
norm_message_value = mapped_message_value / 127
|
||||
|
||||
else:
|
||||
norm_message_value = None
|
||||
self.actions.call_method_name(method_name, norm_message_value)
|
||||
|
||||
|
||||
## 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:
|
||||
self.display.refresh_display()
|
||||
#self.refresh_midi_feedback()
|
||||
# self.refresh_midi_feedback()
|
||||
|
||||
# Plugins to support MIDI feedback
|
||||
|
||||
@@ -143,31 +143,29 @@ class MidiInput(object):
|
||||
# loop over the plugins
|
||||
# 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])
|
||||
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
|
||||
|
||||
for p in self.data.plugins.get_plugins(MidiFeedbackPlugin):
|
||||
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))
|
||||
return p
|
||||
|
||||
print ("Didn't find one!")
|
||||
print("Didn't find one!")
|
||||
|
||||
def refresh_midi_feedback(self):
|
||||
|
||||
self.midi_output.refresh_midi_feedback()
|
||||
|
||||
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):
|
||||
self.root.after(self.midi_delay*5, self.refresh_midi_feedback)
|
||||
|
||||
if self.midi_output.supports_midi_feedback(self.data.midi_device_name):
|
||||
self.root.after(self.midi_delay * 5, self.refresh_midi_feedback)
|
||||
|
||||
def find_binding_for_action(self, action):
|
||||
for bind,a in self.midi_mappings.items():
|
||||
#print("looped over %s : %s " % (bind,a))
|
||||
for (b,c) in a.items():
|
||||
for bind, a in self.midi_mappings.items():
|
||||
# print("looped over %s : %s " % (bind,a))
|
||||
for (b, c) in a.items():
|
||||
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
|
||||
|
||||
|
||||
@@ -23,11 +23,11 @@ class NumpadInput(object):
|
||||
def on_key_press(self, event):
|
||||
numpad = list(string.ascii_lowercase[0:19])
|
||||
|
||||
if event.char is 'h': # DISP button
|
||||
#self.root.after(60, lambda:self.on_key_press_delay(event.char))
|
||||
#return
|
||||
if event.char is 'h': # DISP button
|
||||
# self.root.after(60, lambda:self.on_key_press_delay(event.char))
|
||||
# return
|
||||
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
|
||||
if self.in_0_event:
|
||||
return
|
||||
@@ -47,35 +47,35 @@ class NumpadInput(object):
|
||||
print('{} is not in keypad map'.format(event.char))
|
||||
|
||||
def on_key_release(self, event):
|
||||
numpad = list(string.ascii_lowercase[0:19])
|
||||
if event.char in numpad:
|
||||
self.check_key_release_settings(event.char)
|
||||
numpad = list(string.ascii_lowercase[0:19])
|
||||
if event.char in numpad:
|
||||
self.check_key_release_settings(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
|
||||
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.data.is_display_held = False
|
||||
##print ("--- releasing %s" % event.char)
|
||||
# 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:
|
||||
self.root.after(self.KEY_000_DELAY + 5, self.on_key_disp_release_delay)
|
||||
# self.data.is_display_held = False
|
||||
|
||||
def on_mouse_move(self, event):
|
||||
if self.data.settings['user_input'].setdefault(
|
||||
'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
|
||||
if event.x > 480 or event.y > 320:
|
||||
return
|
||||
width = 480
|
||||
height = 320 # hard coded since display is fixed , and reading screen is more work
|
||||
height = 320 # hard coded since display is fixed , and reading screen is more work
|
||||
|
||||
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.run_action_for_mapped_key(event.char)
|
||||
# self.run_action_for_mapped_key(event.char)
|
||||
|
||||
def select_display_mode_index(self, index):
|
||||
if index >= len(self.data.get_display_modes_list()):
|
||||
self.message_handler.set_message('ERROR', 'No page %s to display!' % index)
|
||||
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):
|
||||
this_mapping = self.key_mappings[key]
|
||||
@@ -101,7 +101,7 @@ class NumpadInput(object):
|
||||
else:
|
||||
print('the numpad action being called for \'{}\' is {} (mode is {})'.format(key, this_mapping[mode][is_function], mode))
|
||||
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:
|
||||
self.actions.call_method_name(this_mapping[mode][is_function])
|
||||
|
||||
@@ -111,10 +111,8 @@ class NumpadInput(object):
|
||||
if not value:
|
||||
self.display.refresh_display()
|
||||
|
||||
|
||||
|
||||
def check_key_release_settings(self, key):
|
||||
|
||||
|
||||
this_mapping = self.key_mappings[key]
|
||||
if self.data.settings['sampler']['ACTION_GATED']['value'] == 'on':
|
||||
if self.data.control_mode == 'PLAYER' and 'PLAYER' in this_mapping:
|
||||
@@ -127,7 +125,7 @@ class NumpadInput(object):
|
||||
self.run_action_for_mapped_key(key)
|
||||
|
||||
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 !")
|
||||
self.data.is_display_held = False
|
||||
else:
|
||||
@@ -140,36 +138,35 @@ class NumpadInput(object):
|
||||
else:
|
||||
print("ignoring press!")"""
|
||||
|
||||
def on_0_key_press(self) :
|
||||
print ("on_0_key_press!")
|
||||
if(not self.in_0_event ):
|
||||
print (" first 0 received!")
|
||||
self.in_0_event = True
|
||||
def on_0_key_press(self):
|
||||
print("on_0_key_press!")
|
||||
if (not self.in_0_event):
|
||||
print(" first 0 received!")
|
||||
self.in_0_event = True
|
||||
self.additional_0_in_event = 0
|
||||
self.root.after(self.KEY_000_DELAY, self.check_event_outcome)
|
||||
else:
|
||||
print (" additional 0 received making %s!" % str(self.additional_0_in_event + 1))
|
||||
self.additional_0_in_event = 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
|
||||
|
||||
def check_event_outcome(self):
|
||||
if(self.additional_0_in_event == 0 ):
|
||||
print (" no additional events, sending s")
|
||||
self.in_0_event = False
|
||||
if (self.additional_0_in_event == 0):
|
||||
print(" no additional events, sending s")
|
||||
self.in_0_event = False
|
||||
self.run_action_for_mapped_key('s')
|
||||
elif(self.additional_0_in_event > 1):
|
||||
print (" %s additional events, sending n"%self.additional_0_in_event)
|
||||
self.in_0_event = False
|
||||
elif (self.additional_0_in_event > 1):
|
||||
print(" %s additional events, sending n" % self.additional_0_in_event)
|
||||
self.in_0_event = False
|
||||
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')
|
||||
self.root.after(self.KEY_000_DELAY, self.second_check_event_outcome)
|
||||
|
||||
def second_check_event_outcome(self):
|
||||
print("not supposed to happen?")
|
||||
if(self.additional_0_in_event == 1 ):
|
||||
self.in_0_event = False
|
||||
if (self.additional_0_in_event == 1):
|
||||
self.in_0_event = False
|
||||
self.run_action_for_mapped_key('s')
|
||||
elif(self.additional_0_in_event > 1):
|
||||
self.in_0_event = False
|
||||
elif (self.additional_0_in_event > 1):
|
||||
self.in_0_event = False
|
||||
self.run_action_for_mapped_key('n')
|
||||
|
||||
|
||||
@@ -14,14 +14,14 @@ class OscInput(object):
|
||||
self.actions = actions
|
||||
self.data = data
|
||||
self.osc_mappings = data.osc_mappings
|
||||
|
||||
|
||||
self.osc_enabled = False
|
||||
self.osc_server = None
|
||||
self.poll_settings_for_osc_info()
|
||||
|
||||
def poll_settings_for_osc_info(self):
|
||||
self.data.settings['user_input'].setdefault('OSC_INPUT',
|
||||
self.data.default_settings['user_input'].get('OSC_INPUT'))
|
||||
self.data.default_settings['user_input'].get('OSC_INPUT'))
|
||||
osc_setting_enabled = self.data.settings['user_input']['OSC_INPUT']['value'] == 'enabled'
|
||||
if osc_setting_enabled and not self.osc_enabled:
|
||||
self.setup_osc_server()
|
||||
@@ -34,7 +34,7 @@ class OscInput(object):
|
||||
def setup_osc_server(self):
|
||||
ip_address = self.data.get_ip_for_osc_client()
|
||||
if ip_address == 'none':
|
||||
self.message_handler.set_message('INFO', 'osc failed - could not find ip')
|
||||
self.message_handler.set_message('INFO', 'osc failed - could not find ip')
|
||||
return
|
||||
print('%%%%%%%%%%%%%%%%%%%%% setting up external_osc on ', ip_address)
|
||||
server_parser = argparse.ArgumentParser()
|
||||
@@ -44,15 +44,15 @@ class OscInput(object):
|
||||
server_args = server_parser.parse_args()
|
||||
|
||||
this_dispatcher = dispatcher.Dispatcher()
|
||||
|
||||
# this_dispatcher.map("/keyboard/*", self.on_osc_input)
|
||||
# this_dispatcher.map("/shaderparam0", 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("/shaderparam3", self.on_param_osc_input)
|
||||
# this_dispatcher.map("/shutdown", self.exit_osc_server)
|
||||
|
||||
# this_dispatcher.map("/keyboard/*", self.on_osc_input)
|
||||
# this_dispatcher.map("/shaderparam0", 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("/shaderparam3", self.on_param_osc_input)
|
||||
# this_dispatcher.map("/shutdown", self.exit_osc_server)
|
||||
this_dispatcher.map("/*", self.on_osc_input)
|
||||
|
||||
|
||||
try:
|
||||
osc_server.ThreadingOSCUDPServer.allow_reuse_address = True
|
||||
server = osc_server.ThreadingOSCUDPServer((server_args.ip, server_args.port), this_dispatcher)
|
||||
@@ -63,7 +63,6 @@ class OscInput(object):
|
||||
except:
|
||||
self.message_handler.set_message('INFO', 'failed to start osc listener')
|
||||
|
||||
|
||||
def exit_osc_server(self, unused_addr, args):
|
||||
print('%%%%%%%%%%%%%%%%%%%%% exiting external_osc')
|
||||
try:
|
||||
@@ -71,7 +70,6 @@ class OscInput(object):
|
||||
self.message_handler.set_message('INFO', 'osc deactive')
|
||||
except:
|
||||
self.message_handler.set_message('INFO', 'osc shutdown failed')
|
||||
|
||||
|
||||
def on_osc_input(self, addr, args):
|
||||
if 'keyboard' in addr:
|
||||
@@ -79,8 +77,7 @@ class OscInput(object):
|
||||
elif 'shutdown' in addr:
|
||||
self.exit_osc_server(addr, args)
|
||||
else:
|
||||
self.on_param_osc_input(addr,args)
|
||||
|
||||
self.on_param_osc_input(addr, args)
|
||||
|
||||
def on_key_osc_input(self, addr, args):
|
||||
args = str(args)
|
||||
@@ -98,7 +95,7 @@ class OscInput(object):
|
||||
print("the address", addr)
|
||||
|
||||
self.run_action_for_osc_channel(addr, param_value=args)
|
||||
|
||||
|
||||
def run_action_for_osc_channel(self, channel, param_value=None):
|
||||
this_mapping = self.osc_mappings[channel]
|
||||
if type(self.data.control_mode) is list:
|
||||
@@ -111,16 +108,15 @@ class OscInput(object):
|
||||
mode = self.data.control_mode
|
||||
elif 'DEFAULT' in this_mapping:
|
||||
mode = 'DEFAULT'
|
||||
|
||||
|
||||
if self.data.function_on and len(this_mapping[mode]) > 1:
|
||||
method_name = this_mapping[mode][1]
|
||||
if self.data.settings['sampler']['FUNC_GATED']['value'] == 'off':
|
||||
self.data.function_on = False
|
||||
else:
|
||||
method_name = this_mapping[mode][0]
|
||||
|
||||
|
||||
self.actions.call_method_name(method_name, param_value)
|
||||
|
||||
if 'continuous' not in method_name:
|
||||
self.display.refresh_display()
|
||||
|
||||
|
||||
@@ -1,23 +1,20 @@
|
||||
|
||||
|
||||
def generate_mappings_doc(title, mappings, column_one_header="Note/CC"):
|
||||
#print(mappings)
|
||||
# print(mappings)
|
||||
output = ""
|
||||
output += "# %s\n" % title
|
||||
output += "\n| %s | Mode | Action (default) | Action (with FN) | \n" % column_one_header
|
||||
output += ("| --- " * 4) + " |\n"
|
||||
for message, maps in sorted(mappings.items()):
|
||||
#output += "| %s | " % message
|
||||
# output += "| %s | " % message
|
||||
for mode, actions in sorted(maps.items()):
|
||||
output += "| "
|
||||
output += "%s\t| " % message
|
||||
output += "%s\t| " % mode
|
||||
output += "%s | " % actions[0]
|
||||
if len(actions)>1:
|
||||
if len(actions) > 1:
|
||||
output += "%s | " % actions[1]
|
||||
output += "|\n"
|
||||
|
||||
output += "\n----\n"
|
||||
|
||||
print(output)
|
||||
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
|
||||
|
||||
class AltVideoPlayer:
|
||||
def __init__(self, root, message_handler, data, osc_client, name):
|
||||
self.root = root
|
||||
@@ -18,15 +16,14 @@ class AltVideoPlayer:
|
||||
self.load_attempts = 0
|
||||
self.alpha = 0
|
||||
self.show_toggle_on = True
|
||||
### new stuff
|
||||
### new stuff
|
||||
self.client = osc_client
|
||||
|
||||
self.position = -1
|
||||
|
||||
|
||||
def try_load(self, layer, is_current=False):
|
||||
load_attempts = 0
|
||||
while(load_attempts < 2):
|
||||
while (load_attempts < 2):
|
||||
load_attempts = load_attempts + 1
|
||||
if self.load(layer, is_current):
|
||||
print('load success')
|
||||
@@ -36,7 +33,6 @@ class AltVideoPlayer:
|
||||
self.message_handler.set_message('ERROR', 'failed to load')
|
||||
self.status = 'ERROR'
|
||||
return False
|
||||
|
||||
|
||||
def load(self, layer, is_current=False):
|
||||
self.get_context_for_player(is_current)
|
||||
@@ -45,9 +41,9 @@ class AltVideoPlayer:
|
||||
self.status = 'EMPTY'
|
||||
return True
|
||||
|
||||
if(self.end is -1):
|
||||
if (self.end is -1):
|
||||
self.end = self.total_length
|
||||
if(self.start is -1):
|
||||
if (self.start is -1):
|
||||
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.crop_length = self.end - self.start
|
||||
@@ -57,10 +53,10 @@ class AltVideoPlayer:
|
||||
pass
|
||||
self.set_alpha_value(0)
|
||||
return True
|
||||
#except (ValueError, SystemError) as e:
|
||||
# print(e)
|
||||
#self.message_handler.set_message('ERROR', 'load attempt fail')
|
||||
#return False
|
||||
# except (ValueError, SystemError) as e:
|
||||
# print(e)
|
||||
# self.message_handler.set_message('ERROR', 'load attempt fail')
|
||||
# return False
|
||||
|
||||
def start_video(self):
|
||||
if 'play' in self.data.settings['sampler']['ON_START']['value']:
|
||||
@@ -73,9 +69,6 @@ class AltVideoPlayer:
|
||||
else:
|
||||
self.set_alpha_value(0)
|
||||
|
||||
|
||||
|
||||
|
||||
def reload(self, layer, is_current=False):
|
||||
self.exit()
|
||||
self.player_running = False
|
||||
@@ -131,7 +124,7 @@ class AltVideoPlayer:
|
||||
|
||||
new_rate = self.rate + amount
|
||||
print('new rate is being set to {}'.format(new_rate))
|
||||
if new_rate >= -3 and new_rate <= 3:
|
||||
if new_rate >= -3 and new_rate <= 3:
|
||||
self.client.send_message("/player/{}/speed".format(self.name[0]), new_rate)
|
||||
self.rate = new_rate
|
||||
return new_rate
|
||||
@@ -149,15 +142,14 @@ class AltVideoPlayer:
|
||||
self.root.after(100, self.exit)
|
||||
|
||||
def exit(self):
|
||||
#self.last_player.exit()
|
||||
# self.last_player.exit()
|
||||
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
|
||||
except:
|
||||
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):
|
||||
if self.data.settings['system']['DEV_MODE_RESET']['value'] == 'on':
|
||||
##self.client.send_message("/player/{}/alpha".format(self.name[0]), amount)
|
||||
@@ -165,17 +157,3 @@ class AltVideoPlayer:
|
||||
else:
|
||||
aspect_mode = self.data.settings['video']['SCREEN_MODE']['value']
|
||||
return False, '--aspect-mode', aspect_mode
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ class Capture(object):
|
||||
self.root = root
|
||||
self.message_handler = message_handler
|
||||
self.data = data
|
||||
|
||||
|
||||
self.device = None
|
||||
self.is_recording = False
|
||||
self.is_previewing = False
|
||||
@@ -23,16 +23,15 @@ class Capture(object):
|
||||
|
||||
## some capture settings
|
||||
|
||||
|
||||
def create_capture_device(self):
|
||||
if self.data.settings['capture']['TYPE']['value'] != 'usb':
|
||||
if self.use_capture:
|
||||
if self.piCapture_with_no_source():
|
||||
return False
|
||||
self.update_capture_settings()
|
||||
|
||||
|
||||
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
|
||||
except picamera.exc.PiCameraError as e:
|
||||
self.use_capture = False
|
||||
@@ -60,16 +59,15 @@ class Capture(object):
|
||||
if self.capture_type == "piCaptureSd1":
|
||||
self.sensor_mode = 6
|
||||
else:
|
||||
self.sensor_mode = 0
|
||||
##update current instance (device) if in use
|
||||
self.sensor_mode = 0
|
||||
##update current instance (device) if in use
|
||||
if self.device and not self.device.closed:
|
||||
self.device.image_effect = self.data.settings['capture']['IMAGE_EFFECT']['value']
|
||||
self.device.shutter_speed = self.convert_shutter_value(self.data.settings['capture']['SHUTTER']['value'])
|
||||
## can only update resolution and framerate if not recording
|
||||
## can only update resolution and framerate if not recording
|
||||
if not self.is_recording:
|
||||
self.device.framerate = self.framerate
|
||||
self.device.resolution = self.resolution
|
||||
|
||||
|
||||
def start_preview(self):
|
||||
if self.use_capture == False:
|
||||
@@ -85,7 +83,7 @@ class Capture(object):
|
||||
self.set_preview_screen_size()
|
||||
self.set_capture_settings()
|
||||
self.device.preview.layer = self.PREVIEW_LAYER
|
||||
return True
|
||||
return True
|
||||
|
||||
def set_capture_settings(self):
|
||||
if self.capture_type == "piCaptureSd1":
|
||||
@@ -95,7 +93,6 @@ class Capture(object):
|
||||
self.device.exposure_mode = "off"
|
||||
else:
|
||||
self.sensor_mode = 0
|
||||
|
||||
|
||||
def set_preview_screen_size(self):
|
||||
if self.data.settings['system']['DEV_MODE_RESET']['value'] == 'on':
|
||||
@@ -121,7 +118,7 @@ class Capture(object):
|
||||
is_created = self.create_capture_device()
|
||||
if self.use_capture == False or not is_created:
|
||||
return
|
||||
|
||||
|
||||
if not os.path.exists(self.video_dir):
|
||||
os.makedirs(self.video_dir)
|
||||
self.is_recording = True
|
||||
@@ -131,7 +128,7 @@ class Capture(object):
|
||||
def monitor_disk_space(self):
|
||||
if self.is_recording:
|
||||
if self.check_available_disk_space():
|
||||
self.root.after(10000, self.monitor_disk_space)
|
||||
self.root.after(10000, self.monitor_disk_space)
|
||||
else:
|
||||
self.stop_recording()
|
||||
|
||||
@@ -145,9 +142,9 @@ class Capture(object):
|
||||
|
||||
def stop_recording(self):
|
||||
self.device.stop_recording()
|
||||
#set status to saving
|
||||
# set status to saving
|
||||
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.update_capture_settings()
|
||||
@@ -156,23 +153,22 @@ class Capture(object):
|
||||
self.device.close()
|
||||
|
||||
def convert_raw_recording(self):
|
||||
recording_path , recording_name = self.generate_recording_path()
|
||||
recording_path, recording_name = self.generate_recording_path()
|
||||
try:
|
||||
if self.sensor_mode == 6:
|
||||
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:
|
||||
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:
|
||||
print(e)
|
||||
if hasattr(e, 'message'):
|
||||
error_info = e.message
|
||||
else:
|
||||
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):
|
||||
print('the poll is {}'.format(process.poll()))
|
||||
if process.poll() is not None:
|
||||
@@ -188,10 +184,10 @@ class Capture(object):
|
||||
os.makedirs(rec_dir)
|
||||
date = datetime.datetime.now().strftime("%Y-%m-%d")
|
||||
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
|
||||
name = 'rec-{}-{}.mp4'.format(date, i)
|
||||
return '{}/{}'.format(rec_dir,name), name
|
||||
return '{}/{}'.format(rec_dir, name), name
|
||||
|
||||
def get_recording_time(self):
|
||||
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
|
||||
else:
|
||||
error_info = e
|
||||
self.message_handler.set_message('ERROR',error_info)
|
||||
self.message_handler.set_message('ERROR', error_info)
|
||||
return 0
|
||||
return 0
|
||||
|
||||
@@ -251,8 +247,7 @@ class Capture(object):
|
||||
def close_capture(self):
|
||||
if self.device is not None:
|
||||
print('closing the old camera...')
|
||||
self.device.close()
|
||||
self.device.close()
|
||||
|
||||
def receive_recording_finished(self, path, value):
|
||||
pass
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ class OfCapture(object):
|
||||
self.osc_client = osc_client
|
||||
self.message_handler = message_handler
|
||||
self.data = data
|
||||
|
||||
|
||||
self.has_capture = False
|
||||
self.is_recording = False
|
||||
self.is_previewing = False
|
||||
@@ -21,7 +21,7 @@ class OfCapture(object):
|
||||
self.recording_start_time = 0
|
||||
self.update_capture_settings()
|
||||
self.of_recording_finished = True
|
||||
#self.create_capture_device()
|
||||
# self.create_capture_device()
|
||||
|
||||
def create_capture_device(self):
|
||||
if self.use_capture and self.capture_type != 'usb':
|
||||
@@ -31,13 +31,12 @@ class OfCapture(object):
|
||||
self.update_capture_settings()
|
||||
if not self.check_if_attached_with_picamera():
|
||||
return
|
||||
|
||||
|
||||
print('sending setup message !', self.capture_type)
|
||||
self.osc_client.send_message("/capture/setup", self.capture_type)
|
||||
self.has_capture = True
|
||||
return True
|
||||
|
||||
|
||||
def piCapture_with_no_source(self):
|
||||
is_piCapture = subprocess.check_output(['pivideo', '--query', 'ready'])
|
||||
if 'Video Processor was not found' not in str(is_piCapture):
|
||||
@@ -57,12 +56,12 @@ class OfCapture(object):
|
||||
if self.capture_type == "piCaptureSd1":
|
||||
self.sensor_mode = 6
|
||||
else:
|
||||
self.sensor_mode = 0
|
||||
|
||||
self.sensor_mode = 0
|
||||
|
||||
def check_if_attached_with_picamera(self):
|
||||
print('about to try open pcamera to check..')
|
||||
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()
|
||||
return True
|
||||
except picamera.exc.PiCameraError as e:
|
||||
@@ -86,7 +85,7 @@ class OfCapture(object):
|
||||
self.update_capture_settings()
|
||||
self.osc_client.send_message("/capture/preview/start", True)
|
||||
return True
|
||||
|
||||
|
||||
def stop_preview(self):
|
||||
self.osc_client.send_message("/capture/preview/stop", True)
|
||||
self.is_previewing = False
|
||||
@@ -103,20 +102,20 @@ class OfCapture(object):
|
||||
|
||||
if not self.check_available_disk_space():
|
||||
return
|
||||
|
||||
|
||||
if not os.path.exists(self.video_dir):
|
||||
os.makedirs(self.video_dir)
|
||||
self.is_recording = True
|
||||
self.of_recording_finished = False
|
||||
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.monitor_disk_space()
|
||||
|
||||
def monitor_disk_space(self):
|
||||
if self.is_recording:
|
||||
if self.check_available_disk_space():
|
||||
self.root.after(10000, self.monitor_disk_space)
|
||||
self.root.after(10000, self.monitor_disk_space)
|
||||
else:
|
||||
self.stop_recording()
|
||||
|
||||
@@ -129,22 +128,21 @@ class OfCapture(object):
|
||||
return True
|
||||
|
||||
def stop_recording(self):
|
||||
#self.device.stop_recording()
|
||||
# self.device.stop_recording()
|
||||
self.osc_client.send_message("/capture/record/stop", True)
|
||||
self.is_recording = 'saving'
|
||||
self.is_recording = 'saving'
|
||||
self.wait_for_raw_file()
|
||||
#set status to saving
|
||||
|
||||
# set status to saving
|
||||
|
||||
def wait_for_raw_file(self):
|
||||
if os.path.exists(self.video_dir + 'raw.h264'):
|
||||
mp4box_process, recording_name = self.convert_raw_recording()
|
||||
|
||||
|
||||
self.root.after(0, self.wait_for_recording_to_save, mp4box_process, recording_name)
|
||||
self.update_capture_settings()
|
||||
elif os.path.exists(self.video_dir + 'raw.mp4') and self.of_recording_finished:
|
||||
recording_path , recording_name = self.generate_recording_path()
|
||||
os.rename(self.video_dir + 'raw.mp4', recording_path )
|
||||
recording_path, recording_name = self.generate_recording_path()
|
||||
os.rename(self.video_dir + 'raw.mp4', recording_path)
|
||||
self.is_recording = False
|
||||
self.data.create_new_slot_mapping_in_first_open(recording_name)
|
||||
self.update_capture_settings()
|
||||
@@ -154,22 +152,21 @@ class OfCapture(object):
|
||||
def convert_raw_recording(self):
|
||||
### wait for omx to finish creating video ...
|
||||
if os.path.exists(self.video_dir + 'raw.h264'):
|
||||
recording_path , recording_name = self.generate_recording_path()
|
||||
framerate = 30 # hardcoded in openframeworks code for now
|
||||
recording_path, recording_name = self.generate_recording_path()
|
||||
framerate = 30 # hardcoded in openframeworks code for now
|
||||
if self.capture_type == "piCaptureSd1":
|
||||
framerate = framerate*2 # because picapture is interlaced
|
||||
framerate = framerate * 2 # because picapture is interlaced
|
||||
try:
|
||||
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:
|
||||
print(e)
|
||||
if hasattr(e, 'message'):
|
||||
error_info = e.message
|
||||
else:
|
||||
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):
|
||||
print('the poll is {}'.format(process.poll()))
|
||||
if process.poll() is not None:
|
||||
@@ -185,10 +182,10 @@ class OfCapture(object):
|
||||
os.makedirs(rec_dir)
|
||||
date = datetime.datetime.now().strftime("%Y-%m-%d")
|
||||
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
|
||||
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):
|
||||
print('recieved recording finshed message !!!!')
|
||||
@@ -196,9 +193,9 @@ class OfCapture(object):
|
||||
|
||||
def get_recording_time(self):
|
||||
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
|
||||
#else:
|
||||
# else:
|
||||
# return self.device.frame.timestamp / 1000000
|
||||
|
||||
def get_preview_alpha(self):
|
||||
@@ -226,6 +223,3 @@ class OfCapture(object):
|
||||
return int(1000000 / self.framerate)
|
||||
else:
|
||||
return int(fractions.Fraction(setting_value) * 1000000)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ from data_centre.plugin_collection import ModulationReceiverPlugin
|
||||
|
||||
class Shaders(object):
|
||||
MENU_HEIGHT = 10
|
||||
EMPTY_SHADER = dict(name='none',is_shader=True,shad_type='-',param_number=4,path='-')
|
||||
EMPTY_SHADER = dict(name='none', is_shader=True, shad_type='-', param_number=4, path='-')
|
||||
|
||||
MAX_MOD_SLOTS = 4
|
||||
|
||||
@@ -17,27 +17,27 @@ class Shaders(object):
|
||||
self.message_handler = message_handler
|
||||
self.message_handler.shaders = self
|
||||
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.focused_param = 0
|
||||
self.shaders_menu_list = self.generate_shaders_list()
|
||||
|
||||
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_param_list = [[0.0,0.0,0.0,0.0] for i in range(3)]
|
||||
|
||||
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_speed_list = [1.0, 1.0, 1.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_value = [0.0] * self.MAX_MOD_SLOTS #,0.0,0.0,0.0]
|
||||
# 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.load_selected_shader()
|
||||
# self.load_selected_shader()
|
||||
|
||||
@property
|
||||
def modulation_level(self):
|
||||
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)])
|
||||
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)])
|
||||
|
||||
def set_modulation_levels(self, levels):
|
||||
self.data.settings['shader']['modulation_level'] = levels
|
||||
@@ -51,17 +51,16 @@ class Shaders(object):
|
||||
has_path, path = self.get_path_for_shader(stripped_name)
|
||||
shad_type = self.determine_shader_type(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))
|
||||
|
||||
else:
|
||||
shaders_menu_list.append(dict(name=line['name'],is_shader=False,shad_type='',param_number=None,path=None))
|
||||
return shaders_menu_list
|
||||
|
||||
shaders_menu_list.append(dict(name=line['name'], is_shader=True, shad_type=shad_type, param_number=parameter_number, path=path))
|
||||
|
||||
else:
|
||||
shaders_menu_list.append(dict(name=line['name'], is_shader=False, shad_type='', param_number=None, path=None))
|
||||
return shaders_menu_list
|
||||
|
||||
def get_path_for_shader(self, file_name):
|
||||
######## returns full path for a given file name ########
|
||||
for path in self.data.PATHS_TO_SHADERS:
|
||||
for path in self.data.PATHS_TO_SHADERS:
|
||||
for root, dirs, files in os.walk(path):
|
||||
if file_name in files:
|
||||
return True, '{}/{}'.format(root, file_name)
|
||||
@@ -69,20 +68,19 @@ class Shaders(object):
|
||||
|
||||
def determine_shader_type(self, path):
|
||||
with open(path, 'r', errors='ignore') as selected_shader:
|
||||
shader_text = selected_shader.read()
|
||||
if '//0-input' in shader_text:
|
||||
return '0in'
|
||||
elif '//1-input' in shader_text:
|
||||
return '1in'
|
||||
elif '//2-input' in shader_text:
|
||||
return '2in'
|
||||
else:
|
||||
return '-'
|
||||
|
||||
shader_text = selected_shader.read()
|
||||
if '//0-input' in shader_text:
|
||||
return '0in'
|
||||
elif '//1-input' in shader_text:
|
||||
return '1in'
|
||||
elif '//2-input' in shader_text:
|
||||
return '2in'
|
||||
else:
|
||||
return '-'
|
||||
|
||||
def determine_shader_parameter_number(self, path):
|
||||
max_amount = 4
|
||||
if True: # for now always assume 4 params
|
||||
if True: # for now always assume 4 params
|
||||
return max_amount
|
||||
with open(path, 'r') as selected_shader:
|
||||
shader_text = selected_shader.read()
|
||||
@@ -93,9 +91,9 @@ class Shaders(object):
|
||||
|
||||
def load_shader_layer(self, 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)
|
||||
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] == '▶':
|
||||
self.selected_status_list[layer] = '■'
|
||||
|
||||
@@ -121,7 +119,7 @@ class Shaders(object):
|
||||
def map_on_shaders_selection(self):
|
||||
index = self.shaders_menu.selected_list_index
|
||||
is_file, name = self.shaders_menu.extract_file_type_and_name_from_menu_format(
|
||||
self.shaders_menu_list[index]['name'])
|
||||
self.shaders_menu_list[index]['name'])
|
||||
if is_file:
|
||||
is_successful = self.data.create_new_shader_mapping_in_first_open(name)
|
||||
if not is_successful:
|
||||
@@ -133,7 +131,7 @@ class Shaders(object):
|
||||
selected_shader = self.selected_shader_list[self.data.shader_layer]
|
||||
index = self.shaders_menu.selected_list_index
|
||||
is_file, name = self.shaders_menu.extract_file_type_and_name_from_menu_format(
|
||||
self.shaders_menu_list[index]['name'])
|
||||
self.shaders_menu_list[index]['name'])
|
||||
is_selected_shader = False
|
||||
if is_file and name == selected_shader['name'].lstrip():
|
||||
is_selected_shader = True
|
||||
@@ -152,7 +150,7 @@ class Shaders(object):
|
||||
self.selected_shader_list[layer]['slot'] = slot
|
||||
self.load_shader_layer(layer)
|
||||
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):
|
||||
print(self.data.shader_bank_data[self.data.shader_layer])
|
||||
@@ -161,15 +159,15 @@ class Shaders(object):
|
||||
def increase_this_param(self, amount_change):
|
||||
param = self.focused_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)
|
||||
|
||||
def decrease_this_param(self, amount_change):
|
||||
param = self.focused_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)
|
||||
|
||||
|
||||
def toggle_shader_speed(self):
|
||||
if self.selected_speed_list[self.data.shader_layer] > 0.62:
|
||||
self.set_speed_to_amount(0.5)
|
||||
@@ -190,11 +188,11 @@ class Shaders(object):
|
||||
def select_previous_shader_modulation_slot(self):
|
||||
self.selected_modulation_slot -= 1
|
||||
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):
|
||||
for layer in self.modulation_level:
|
||||
for layer,levels in enumerate(layer):
|
||||
for layer, levels in enumerate(layer):
|
||||
levels[slot] = 0.0
|
||||
|
||||
def reset_selected_modulation(self):
|
||||
@@ -206,13 +204,13 @@ class Shaders(object):
|
||||
return 1
|
||||
elif current + change < 0:
|
||||
return 0
|
||||
else:
|
||||
else:
|
||||
return current + change
|
||||
|
||||
|
||||
def set_param_to_amount(self, param, amount, layer_offset=None):
|
||||
start_layer = self.data.shader_layer
|
||||
if self.data.settings['shader']['FIX_PARAM_OFFSET_LAYER']['value'] == 'enabled':
|
||||
start_layer = 0
|
||||
start_layer = 0
|
||||
if layer_offset is None:
|
||||
start_layer = self.data.shader_layer
|
||||
layer_offset = 0
|
||||
@@ -222,45 +220,47 @@ class Shaders(object):
|
||||
|
||||
def set_param_layer_to_amount(self, param, layer, amount):
|
||||
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)
|
||||
else:
|
||||
self.set_speed_layer_to_amount(layer, amount) # layer_offset=layer-self.data.shader_layer)
|
||||
else:
|
||||
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):
|
||||
l = []
|
||||
for i,v in enumerate(values):
|
||||
for i, v in enumerate(values):
|
||||
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)
|
||||
|
||||
def get_modulation_value(self, amount, value, level):
|
||||
if level==0:
|
||||
if level == 0:
|
||||
return amount
|
||||
|
||||
# TODO: read from list of input formulas, from plugins etc to modulate the value
|
||||
temp_amount = amount + (value * level)
|
||||
#print("from amount %s, modulation is %s, temp_amount is %s" % (amount, modulation, temp_amount))
|
||||
if temp_amount < 0: temp_amount = 0 # input range is 0-1 so convert back
|
||||
if temp_amount > 1: temp_amount = 1 # modulation however is -1 to +1
|
||||
# print("from amount %s, modulation is %s, temp_amount is %s" % (amount, modulation, temp_amount))
|
||||
if temp_amount < 0:
|
||||
temp_amount = 0 # input range is 0-1 so convert back
|
||||
if temp_amount > 1:
|
||||
temp_amount = 1 # modulation however is -1 to +1
|
||||
|
||||
return temp_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):
|
||||
# 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):
|
||||
plugin.set_modulation_value(param, self.modulation_value[param])
|
||||
for layer,params in enumerate(self.selected_param_list):
|
||||
for ip,p in enumerate(params):
|
||||
for p2,v in enumerate(self.modulation_level[layer][ip]):
|
||||
if v!=0:
|
||||
self.update_param_layer(ip,layer)
|
||||
break
|
||||
for layer, params in enumerate(self.selected_param_list):
|
||||
for ip, p in enumerate(params):
|
||||
for p2, v in enumerate(self.modulation_level[layer][ip]):
|
||||
if v != 0:
|
||||
self.update_param_layer(ip, layer)
|
||||
break
|
||||
|
||||
def set_param_layer_offset_modulation_level(self, param, layer, level):
|
||||
layer = (self.data.shader_layer + layer) % 3
|
||||
@@ -277,12 +277,12 @@ class Shaders(object):
|
||||
# merge all applicable layers
|
||||
|
||||
self.send_param_layer_amount_message(param, layer,
|
||||
self.get_modulation_value_list(
|
||||
self.selected_param_list[layer][param],
|
||||
self.modulation_value,#[0], #param],
|
||||
self.modulation_level[layer][param]
|
||||
)
|
||||
)
|
||||
self.get_modulation_value_list(
|
||||
self.selected_param_list[layer][param],
|
||||
self.modulation_value, # [0], #param],
|
||||
self.modulation_level[layer][param]
|
||||
)
|
||||
)
|
||||
|
||||
def set_speed_offset_to_amount(self, layer_offset, amount):
|
||||
self.set_speed_to_amount(amount, layer_offset)
|
||||
@@ -290,8 +290,7 @@ class Shaders(object):
|
||||
def set_speed_to_amount(self, amount, layer_offset=0):
|
||||
layer = (self.data.shader_layer + layer_offset) % 3
|
||||
self.set_speed_layer_to_amount(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
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ from video_centre.video_player import VideoPlayer
|
||||
|
||||
|
||||
class VideoDriver(object):
|
||||
|
||||
MAX_LAYER = 254
|
||||
|
||||
def __init__(self, root, osc_client, message_handler, data):
|
||||
@@ -16,28 +15,26 @@ class VideoDriver(object):
|
||||
self.in_current_playing_cycle = False
|
||||
self.in_next_load_cycle = False
|
||||
self.in_parallel_cycle = False
|
||||
|
||||
|
||||
self.layer = self.MAX_LAYER
|
||||
|
||||
self.last_player = None
|
||||
self.current_player = None
|
||||
self.next_player = None
|
||||
self.reset_all_players()
|
||||
|
||||
|
||||
self.update_video_settings()
|
||||
if self.loop_parallel:
|
||||
self.in_parallel_cycle = True
|
||||
self.root.after(self.delay, self.begin_playing_parallel)
|
||||
else:
|
||||
self.root.after(self.delay, self.begin_playing)
|
||||
#self.print_status()
|
||||
|
||||
|
||||
# self.print_status()
|
||||
|
||||
def update_video_settings(self):
|
||||
self.switch_on_finish = self.data.settings['sampler']['ON_FINISH']['value'] == 'switch'
|
||||
self.loop_parallel = self.data.settings['sampler']['LOOP_TYPE']['value'] == 'parallel'
|
||||
|
||||
|
||||
def get_next_layer_value(self):
|
||||
if self.layer > 0:
|
||||
self.layer = self.layer - 1
|
||||
@@ -49,8 +46,8 @@ class VideoDriver(object):
|
||||
def print_status(self):
|
||||
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, \
|
||||
self.current_player.status, self.next_player.name, self.next_player.status,))
|
||||
self.root.after(1000,self.print_status)
|
||||
self.current_player.status, self.next_player.name, self.next_player.status, ))
|
||||
self.root.after(1000, self.print_status)
|
||||
|
||||
def begin_playing(self):
|
||||
if self.current_player.try_load(self.get_next_layer_value()):
|
||||
@@ -68,11 +65,11 @@ class VideoDriver(object):
|
||||
self.root.after(self.delay, self.wait_for_first_load)
|
||||
|
||||
def switch_players_and_start_video(self):
|
||||
self.in_first_load_cycle = False
|
||||
self.in_current_playing_cycle = False
|
||||
self.in_next_load_cycle = True
|
||||
self.in_first_load_cycle = False
|
||||
self.in_current_playing_cycle = False
|
||||
self.in_next_load_cycle = True
|
||||
|
||||
self.switch_players()
|
||||
self.switch_players()
|
||||
|
||||
def switch_players(self):
|
||||
temp_player = self.last_player
|
||||
@@ -84,7 +81,7 @@ class VideoDriver(object):
|
||||
|
||||
def start_video(self):
|
||||
self.current_player.start_video()
|
||||
self.last_player.exit()
|
||||
self.last_player.exit()
|
||||
self.next_player.try_load(self.get_next_layer_value())
|
||||
self.in_current_playing_cycle = True
|
||||
self.wait_for_next_cycle()
|
||||
@@ -115,10 +112,9 @@ class VideoDriver(object):
|
||||
else:
|
||||
self.in_next_load_cycle = False
|
||||
|
||||
|
||||
def get_player_info_for_status(self):
|
||||
return self.current_player.bankslot_number, self.current_player.status, self.current_player.alpha, \
|
||||
self.next_player.bankslot_number, self.next_player.status, self.next_player.alpha
|
||||
self.next_player.bankslot_number, self.next_player.status, self.next_player.alpha
|
||||
|
||||
def get_player_info_for_banner(self, player):
|
||||
if player == 'now':
|
||||
@@ -130,20 +126,20 @@ class VideoDriver(object):
|
||||
if self.next_player:
|
||||
self.next_player.exit()
|
||||
if self.current_player:
|
||||
self.current_player.exit()
|
||||
if self. last_player:
|
||||
self.current_player.exit()
|
||||
if self.last_player:
|
||||
self.last_player.exit()
|
||||
|
||||
def reset_all_players(self):
|
||||
self.exit_all_players()
|
||||
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.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')
|
||||
else:
|
||||
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')
|
||||
|
||||
def reload_next_player(self):
|
||||
@@ -154,7 +150,7 @@ class VideoDriver(object):
|
||||
|
||||
def receive_position(self, unused_addr, player_name, args):
|
||||
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
|
||||
break
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from omxplayer.player import OMXPlayer
|
||||
|
||||
|
||||
class VideoPlayer:
|
||||
def __init__(self, root, message_handler, data, name):
|
||||
self.root = root
|
||||
@@ -20,10 +21,9 @@ class VideoPlayer:
|
||||
self.alpha = 0
|
||||
self.show_toggle_on = False
|
||||
|
||||
|
||||
def try_load(self, layer, is_current=False):
|
||||
load_attempts = 0
|
||||
while(load_attempts < 2):
|
||||
while (load_attempts < 2):
|
||||
load_attempts = load_attempts + 1
|
||||
if self.load(layer, is_current):
|
||||
print('load success')
|
||||
@@ -33,10 +33,9 @@ class VideoPlayer:
|
||||
self.message_handler.set_message('ERROR', 'failed to load')
|
||||
self.status = 'ERROR'
|
||||
return False
|
||||
|
||||
|
||||
def load(self, layer, is_current=False):
|
||||
#try:
|
||||
# try:
|
||||
self.get_context_for_player(is_current)
|
||||
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]
|
||||
@@ -49,10 +48,10 @@ class VideoPlayer:
|
||||
return True
|
||||
self.omx_player = OMXPlayer(self.location, args=arguments, dbus_name=self.name)
|
||||
self.omx_running = True
|
||||
self.total_length = self.omx_player.duration() # <-- uneeded once self.duration stores float
|
||||
if(self.end is -1):
|
||||
self.total_length = self.omx_player.duration() # <-- uneeded once self.duration stores float
|
||||
if (self.end is -1):
|
||||
self.end = self.total_length
|
||||
if(self.start is -1):
|
||||
if (self.start is -1):
|
||||
self.start = 0
|
||||
self.crop_length = self.end - self.start
|
||||
print('{}: the duration is {}'.format(self.name, self.total_length))
|
||||
@@ -64,14 +63,14 @@ class VideoPlayer:
|
||||
self.set_alpha_value(0)
|
||||
self.pause_at_start()
|
||||
return True
|
||||
#except (ValueError, SystemError) as e:
|
||||
# print(e)
|
||||
#self.message_handler.set_message('ERROR', 'load attempt fail')
|
||||
#return False
|
||||
# except (ValueError, SystemError) as e:
|
||||
# print(e)
|
||||
# self.message_handler.set_message('ERROR', 'load attempt fail')
|
||||
# return False
|
||||
|
||||
def pause_at_start(self):
|
||||
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 self.status == 'LOADING':
|
||||
self.status = 'LOADED'
|
||||
@@ -94,12 +93,12 @@ class VideoPlayer:
|
||||
def pause_at_end(self):
|
||||
position = self.get_position()
|
||||
end_threshold = self.end - 0.2
|
||||
if(position > end_threshold):
|
||||
if (position > end_threshold):
|
||||
self.status = 'FINISHED'
|
||||
self.omx_player.pause()
|
||||
|
||||
|
||||
print('its paused at end!')
|
||||
elif(self.omx_running):
|
||||
elif (self.omx_running):
|
||||
self.root.after(5, self.pause_at_end)
|
||||
|
||||
def reload(self, layer, is_current=False):
|
||||
@@ -123,7 +122,7 @@ class VideoPlayer:
|
||||
def get_context_for_player(self, is_current=False):
|
||||
next_context = self.data.get_next_context(is_current)
|
||||
self.location = next_context['location']
|
||||
#self.total_length = next_context['length']
|
||||
# self.total_length = next_context['length']
|
||||
self.start = next_context['start']
|
||||
self.end = next_context['end']
|
||||
self.bankslot_number = next_context['bankslot_number']
|
||||
@@ -152,7 +151,7 @@ class VideoPlayer:
|
||||
after_seek_position = position + amount
|
||||
if after_seek_position > self.start and after_seek_position < self.end:
|
||||
self.set_position(after_seek_position)
|
||||
#self.player.seek(amount)
|
||||
# self.player.seek(amount)
|
||||
else:
|
||||
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()):
|
||||
updated_speed = self.omx_player.set_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
|
||||
else:
|
||||
self.message_handler.set_message('INFO', 'can not set speed outside of range')
|
||||
@@ -173,7 +172,7 @@ class VideoPlayer:
|
||||
def exit(self):
|
||||
try:
|
||||
if self.omx_player:
|
||||
print('trying to exit this player ', self.location)
|
||||
print('trying to exit this player ', self.location)
|
||||
self.omx_player.quit()
|
||||
self.status = 'EMPTY'
|
||||
self.omx_running = False
|
||||
@@ -187,5 +186,3 @@ class VideoPlayer:
|
||||
else:
|
||||
aspect_mode = self.data.settings['video']['SCREEN_MODE']['value']
|
||||
return False, '--aspect-mode', aspect_mode
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user