def setup_gui(self): # top lvl self.frame = tk.Frame(self.root) self.info_frame = tk.Frame(self.frame) # name, mayb add tags/way to edit/add/delete these things self.progress_frame = tk.Frame(self.frame) self.control_frame = tk.Frame(self.frame) self.name_var = tk.StringVar() self.name_label = tk.Label(self.info_frame,textvariable=self.name_var,relief=tk.RIDGE) self.name_label.pack(side=tk.TOP,fill=tk.X) # bottom half self.left_half = tk.Frame(self.control_frame) self.right_half = tk.Frame(self.control_frame) # bottom left self.cue_button_frame = tk.Frame(self.left_half) self.loop_ctrl_frame = tk.Frame(self.left_half) # bottom right self.control_button_frame = tk.Frame(self.right_half) self.param_frame = tk.Frame(self.right_half) self.loop_param_frame = tk.Frame(self.right_half) # subparams self.playback_speed_frame = tk.Frame(self.param_frame) self.control_speed_frame = tk.Frame(self.param_frame) # pack it self.info_frame.pack(side=tk.TOP) self.progress_frame.pack(side=tk.TOP) self.control_frame.pack(side=tk.TOP) self.left_half.pack(side=tk.LEFT) self.right_half.pack(side=tk.LEFT) # l self.cue_button_frame.pack(side=tk.TOP) self.loop_ctrl_frame.pack(side=tk.TOP) # r self.control_button_frame.pack(side=tk.TOP) self.param_frame.pack(side=tk.TOP) self.loop_param_frame.pack(side=tk.TOP) self.playback_speed_frame.pack(side=tk.TOP) self.control_speed_frame.pack(side=tk.TOP) self.progress_bar = ProgressBar(self,self.clip,root=self.progress_frame,width=300) self.progress_bar.map_osc(self.clip.control_addr) self.cue_buttons = [] self.setup_cue_buttons() self.looping_controls = [] self.looping_vars = {} self.setup_looping() self.control_buttons = [] self.setup_control_buttons() self.frame.pack()
class ClipControl: def __init__(self,root,backend,clip=None): # sol stuff if not clip: clip = backend.cur_clip self.clip = clip #self.clip.control_addr = '/activeclip/video/position/values' # temp for activeclip only self.backend = backend self.osc_client = self.backend.osc_client self.osc_server = self.backend.osc_server ### tk stuff self.root = root self.setup_gui() self.change_clip(self.clip) def change_clip(self,newclip): # activated when clip is changed, whether on first time setup or on backend cur_clip change if newclip != self.clip: self.clip = newclip self.progress_bar.cliporsong = newclip self.update_info() def update_mapping(self): self.osc_client.map_loop() self.osc_client.map_timeline() def setup_gui(self): # top lvl self.frame = tk.Frame(self.root) self.info_frame = tk.Frame(self.frame) # name, mayb add tags/way to edit/add/delete these things self.progress_frame = tk.Frame(self.frame) self.control_frame = tk.Frame(self.frame) self.name_var = tk.StringVar() self.name_label = tk.Label(self.info_frame,textvariable=self.name_var,relief=tk.RIDGE) self.name_label.pack(side=tk.TOP,fill=tk.X) # bottom half self.left_half = tk.Frame(self.control_frame) self.right_half = tk.Frame(self.control_frame) # bottom left self.cue_button_frame = tk.Frame(self.left_half) self.loop_ctrl_frame = tk.Frame(self.left_half) # bottom right self.control_button_frame = tk.Frame(self.right_half) self.param_frame = tk.Frame(self.right_half) self.loop_param_frame = tk.Frame(self.right_half) # subparams self.playback_speed_frame = tk.Frame(self.param_frame) self.control_speed_frame = tk.Frame(self.param_frame) # pack it self.info_frame.pack(side=tk.TOP) self.progress_frame.pack(side=tk.TOP) self.control_frame.pack(side=tk.TOP) self.left_half.pack(side=tk.LEFT) self.right_half.pack(side=tk.LEFT) # l self.cue_button_frame.pack(side=tk.TOP) self.loop_ctrl_frame.pack(side=tk.TOP) # r self.control_button_frame.pack(side=tk.TOP) self.param_frame.pack(side=tk.TOP) self.loop_param_frame.pack(side=tk.TOP) self.playback_speed_frame.pack(side=tk.TOP) self.control_speed_frame.pack(side=tk.TOP) self.progress_bar = ProgressBar(self,self.clip,root=self.progress_frame,width=300) self.progress_bar.map_osc(self.clip.control_addr) self.cue_buttons = [] self.setup_cue_buttons() self.looping_controls = [] self.looping_vars = {} self.setup_looping() self.control_buttons = [] self.setup_control_buttons() self.frame.pack() def update_info(self): # update me try: if self.clip: self.name_var.set(self.clip.name) self.update_cue_buttons() self.update_looping() self.update_pbar() self.update_mapping() except: pass def update_pbar(self): #self.progress_bar.map_osc(self.clip.control_addr) self.progress_bar.send_addr = self.clip.control_addr def move_cue(i,x): self.osc_client.set_q(self.clip,i,x) self.progress_bar.drag_release_action = move_cue # clear the screen of any junk self.progress_bar.loop_update() def setup_cue_buttons(self): n_buts = len(self.clip.vars['qp']) n_rows = 1 if n_buts > 4: n_rows = n_buts // 4 if n_buts % 4 != 0: n_rows += 1 # yuck for r in range(n_rows): for c in range(4): i = r*4 + c but = tk.Button(self.cue_button_frame,text=str(i),padx=10,pady=10,relief='flat') but.grid(row=r,column=c) if i + 1 > n_buts: but.config(state='disabled') self.cue_buttons.append(but) def update_cue_buttons(self): n_buts = len(self.clip.vars['qp']) n_rows = 1 if n_buts > 4: n_rows = n_buts // 4 if n_buts % 4 != 0: n_rows += 1 # yuck def gen_activate(i): def tor(): new = self.osc_client.activate(self.clip,i) # add return value self.cue_buttons[i].config(relief='groove') if new: self.progress_bar.add_line(new,i) return tor def gen_deactivate(i): def tor(*args): self.osc_client.clear_q(self.clip,i) self.cue_buttons[i].config(relief='flat') self.progress_bar.remove_line(i) return tor self.activate_funs = [gen_activate(i) for i in range(C.NO_Q)] self.deactivate_funs = [gen_deactivate(i) for i in range(C.NO_Q)] for r in range(n_rows): for c in range(4): i = r*4 + c but = self.cue_buttons[i] # tie it to fxn of q_points if i + 1 <= n_buts: but.config(command=self.activate_funs[i],state='active') but.bind("<ButtonPress-3>",self.deactivate_funs[i]) self.progress_bar.remove_line(i) # remove old shit else: but.config(state='disabled') if self.clip.vars['qp'][i]: but.config(relief='groove') # make it so button is grooved if has cue self.progress_bar.add_line(self.clip.vars['qp'][i],i) else: but.config(relief='flat') def gen_osc_sender(self,addr,msg): osc_msg = self.osc_client.build_msg(addr,msg) def fun_tor(*args): self.osc_client.send(osc_msg) return fun_tor def setup_control_buttons(self): playbut = tk.Button(self.control_button_frame,text=">",padx=8,pady=8, command=lambda:self.osc_client.play(self.clip)) pausebut = tk.Button(self.control_button_frame,text="||",padx=7,pady=8, command=lambda:self.osc_client.pause(self.clip)) rvrsbut = tk.Button(self.control_button_frame,text="<",padx=8,pady=8, command=lambda:self.osc_client.reverse(self.clip)) rndbut = tk.Button(self.control_button_frame,text="*",padx=8,pady=8, command=lambda:self.osc_client.random_play(self.clip)) clearbut = tk.Button(self.control_button_frame,text="X",padx=8,pady=8, command=lambda:self.osc_client.clear()) for but in [playbut, pausebut, rvrsbut, rndbut, clearbut]: but.pack(side=tk.LEFT) def setup_looping(self): """ control panel for looping between any two cue points also can control playback speed, and the (eventual) controller -> timeshift transpose rate for now has 2 dropdowns.. and 2 spinboxes """ loop_poss = [str(i) for i in range(C.NO_Q)] self.loop_to_clip_var = {'loop_a':['lp',0],'loop_b':['lp',1], 'loop_type' : ['looptype'], 'speed':['playback_speed'],'control_speed':['speedup_factor']} for key in self.loop_to_clip_var: self.looping_vars[key] = tk.StringVar() # speedup (of playback) speed_scale = tk.Scale(self.playback_speed_frame,from_=0.0,to=10.0,resolution=0.05,variable=self.looping_vars['speed'], orient=tk.HORIZONTAL, showvalue = 0) speed_box = tk.Spinbox(self.playback_speed_frame,from_=0.0,to=10.0,increment=0.1,format="%.2f", textvariable=self.looping_vars['speed'], width=4) def send_speed(*args): #### TO-DO add global speedvar speed = float(self.looping_vars['speed'].get())/10.0 self.osc_client.build_n_send('/activeclip/video/position/speed',speed) speed_scale.config(command=send_speed) speed_box.config(command=send_speed) speed_box.bind("<Return>",send_speed) self.looping_controls.append(speed_scale) self.looping_controls.append(speed_box) self.speed_increase = lambda: speed_box.invoke("buttonup") self.speed_decrease = lambda: speed_box.invoke("buttondown") # speedup of control? control_speed_scale = tk.Scale(self.control_speed_frame,from_=1.0,to=C.MAX_SPEEDUP,resolution=0.01,variable=self.looping_vars['control_speed'], orient=tk.HORIZONTAL, showvalue = 0) control_speed_box = tk.Spinbox(self.control_speed_frame,from_=1.0,to=C.MAX_SPEEDUP,increment=0.03,format="%.2f", textvariable=self.looping_vars['control_speed'], width=4) self.looping_controls.append(control_speed_scale) self.looping_controls.append(control_speed_box) self.speedup_increase = lambda: control_speed_box.invoke("buttonup") self.speedup_decrease = lambda: control_speed_box.invoke("buttondown") # loop selection loop_select_a = tk.OptionMenu(self.loop_ctrl_frame,self.looping_vars['loop_a'],*loop_poss) loop_select_b = tk.OptionMenu(self.loop_ctrl_frame,self.looping_vars['loop_b'],*loop_poss) self.looping_controls.append(loop_select_a) self.looping_controls.append(loop_select_b) self.loop_on_off = tk.Button(self.loop_ctrl_frame,text='loop',command=self.toggle_looping) self.looping_controls.append(self.loop_on_off) loop_select_type = tk.OptionMenu(self.loop_param_frame,self.looping_vars['loop_type'],'default','bounce') self.looping_controls.append(loop_select_type) for control in self.looping_controls: control.pack(side=tk.LEFT) def change_speed(self,n): if isinstance(n, int): if n > 0: for _ in range(n): self.speed_increase() else: for _ in range(-1*n): self.speed_decrease() else: self.looping_vars['speed'].set("%.2f" % (10.0 * n)) def change_speedup(self,n): if isinstance(n, int): if n > 0: for _ in range(n): self.speedup_increase() else: for _ in range(-1*n): self.speedup_decrease() else: self.looping_vars['control_speed'].set("%.2f" % (C.MAX_SPEEDUP * n)) self.osc_client.build_n_send('/composition/video/effect1/opacity/values',self.backend.cur_clip_pos.value/self.clip.vars['speedup_factor']) def change_lp(self,new_lp): self.looping_vars['loop_a'].set(str(new_lp[0])) self.looping_vars['loop_b'].set(str(new_lp[1])) def update_looping(self): # set all variables to their current values def update_loop_var(which_one): # reverse of below fxn try: lookup = self.loop_to_clip_var[which_one] if len(lookup) > 1: self.looping_vars[which_one].set(str(self.clip.vars[lookup[0]][lookup[1]])) else: self.looping_vars[which_one].set(str(self.clip.vars[lookup[0]])) except: print('{} failed to update'.format(which_one)) for key in self.loop_to_clip_var: update_loop_var(key) def gen_update_clip_var(which_one): # depends on the clipvar to be set to proper type ahead of time :) lookup = self.loop_to_clip_var[which_one] if len(lookup) > 1: def fun_tor(*args): newtype = type(self.clip.vars[lookup[0]][lookup[1]]) self.clip.vars[lookup[0]][lookup[1]] = newtype(self.looping_vars[which_one].get()) else: def fun_tor(*args): newtype = type(self.clip.vars[lookup[0]]) self.clip.vars[lookup[0]] = newtype(self.looping_vars[which_one].get()) return fun_tor def gen_update_pbar_related_var(which_one): doit = gen_update_clip_var(which_one) def fun_tor(*args): doit() self.progress_bar.refresh() return fun_tor for key in self.loop_to_clip_var: if key in ['loop_a','loop_b']: self.looping_vars[key].trace('w', gen_update_pbar_related_var(key)) else: self.looping_vars[key].trace('w', gen_update_clip_var(key)) self.looping_but_check() def toggle_looping(self): self.clip.vars['loopon'] = not self.clip.vars['loopon'] self.progress_bar.refresh() self.looping_but_check() def looping_but_check(self): if self.clip.vars['loopon']: self.loop_on_off.config(relief='sunken') else: self.loop_on_off.config(relief='raised') def toggle_loop_type(self): if self.looping_vars['loop_type'].get() == 'default': self.looping_vars['loop_type'].set('bounce') else: self.looping_vars['loop_type'].set('default')