comparison bin/keyboardcomposer @ 1390:6326a26e548c

clean lint in KC Ignore-this: 8a57800d27e68a7f2e46534a8d528fe9
author Drew Perttula <drewp@bigasterisk.com>
date Thu, 09 Jun 2016 07:07:55 +0000
parents 1b6583740f76
children 4a7594476905
comparison
equal deleted inserted replaced
1389:247c193ed5af 1390:6326a26e548c
1 #!bin/python 1 #!bin/python
2 2
3 from __future__ import division, nested_scopes 3 from __future__ import division, nested_scopes
4 from run_local import log 4 from run_local import log
5 import cgi, os, sys, time, subprocess, logging, random 5 import cgi, time, logging
6 from optparse import OptionParser 6 from optparse import OptionParser
7 import webcolors, colorsys 7 import webcolors, colorsys
8 from louie import dispatcher 8 from louie import dispatcher
9 from twisted.internet import reactor, tksupport 9 from twisted.internet import reactor, tksupport
10 from twisted.web import xmlrpc, server, resource 10 from twisted.web import server, resource
11 from rdflib import URIRef, Literal, RDF 11 from rdflib import URIRef, Literal
12 from Tix import *
13 import Tix as tk 12 import Tix as tk
14 import pickle
15 13
16 from light9.Fadable import Fadable 14 from light9.Fadable import Fadable
17 from light9.Submaster import Submasters, sub_maxes, PersistentSubmaster 15 from light9.Submaster import Submasters, sub_maxes, PersistentSubmaster
18 from light9.Patch import get_channel_uri 16 from light9.Patch import get_channel_uri
19 from light9.subclient import SubClient 17 from light9.subclient import SubClient
20 from light9 import dmxclient, showconfig, networking, prof 18 from light9 import showconfig, networking, prof
21 from light9.uihelpers import toplevelat, bindkeys 19 from light9.uihelpers import toplevelat
22 from light9.namespaces import L9 20 from light9.namespaces import L9
23 from light9.tkdnd import initTkdnd, dragSourceRegister, dropTargetRegister 21 from light9.tkdnd import initTkdnd, dragSourceRegister, dropTargetRegister
24 from light9.rdfdb import clientsession 22 from light9.rdfdb import clientsession
25 from light9.rdfdb.syncedgraph import SyncedGraph 23 from light9.rdfdb.syncedgraph import SyncedGraph
26 from light9.rdfdb.patch import Patch
27 24
28 from bcf2000 import BCF2000 25 from bcf2000 import BCF2000
29 26
30 nudge_keys = { 27 nudge_keys = {
31 'up' : list('qwertyui'), 28 'up' : list('qwertyui'),
38 def close(self): 35 def close(self):
39 pass 36 pass
40 def reopen(self): 37 def reopen(self):
41 pass 38 pass
42 39
43 class SubScale(Scale, Fadable): 40 class SubScale(tk.Scale, Fadable):
44 def __init__(self, master, *args, **kw): 41 def __init__(self, master, *args, **kw):
45 self.scale_var = kw.get('variable') or DoubleVar() 42 self.scale_var = kw.get('variable') or tk.DoubleVar()
46 kw.update({'variable' : self.scale_var, 43 kw.update({'variable' : self.scale_var,
47 'from' : 1, 'to' : 0, 'showvalue' : 0, 44 'from' : 1, 'to' : 0, 'showvalue' : 0,
48 'sliderlength' : 15, 'res' : 0.01, 45 'sliderlength' : 15, 'res' : 0.01,
49 'width' : 40, 'troughcolor' : 'black', 'bg' : 'grey40', 46 'width' : 40, 'troughcolor' : 'black', 'bg' : 'grey40',
50 'highlightthickness' : 1, 'bd' : 1, 47 'highlightthickness' : 1, 'bd' : 1,
51 'highlightcolor' : 'red', 'highlightbackground' : 'black', 48 'highlightcolor' : 'red', 'highlightbackground' : 'black',
52 'activebackground' : 'red'}) 49 'activebackground' : 'red'})
53 Scale.__init__(self, master, *args, **kw) 50 tk.Scale.__init__(self, master, *args, **kw)
54 Fadable.__init__(self, var=self.scale_var, wheel_step=0.05) 51 Fadable.__init__(self, var=self.scale_var, wheel_step=0.05)
55 self.draw_indicator_colors() 52 self.draw_indicator_colors()
56 def draw_indicator_colors(self): 53 def draw_indicator_colors(self):
57 if self.scale_var.get() == 0: 54 if self.scale_var.get() == 0:
58 self['troughcolor'] = 'black' 55 self['troughcolor'] = 'black'
59 else: 56 else:
60 self['troughcolor'] = 'blue' 57 self['troughcolor'] = 'blue'
61 58
62 class SubmasterBox(Frame): 59 class SubmasterBox(tk.Frame):
63 """ 60 """
64 this object owns the level of the submaster (the rdf graph is the 61 this object owns the level of the submaster (the rdf graph is the
65 real authority) 62 real authority)
66 """ 63 """
67 def __init__(self, master, sub, session, col, row): 64 def __init__(self, master, sub, session, col, row):
71 bg = sub.graph.value(sub.uri, L9.color, default='#000000') 68 bg = sub.graph.value(sub.uri, L9.color, default='#000000')
72 rgb = webcolors.hex_to_rgb(bg) 69 rgb = webcolors.hex_to_rgb(bg)
73 hsv = colorsys.rgb_to_hsv(*[x/255 for x in rgb]) 70 hsv = colorsys.rgb_to_hsv(*[x/255 for x in rgb])
74 darkBg = webcolors.rgb_to_hex(tuple([x * 255 for x in colorsys.hsv_to_rgb( 71 darkBg = webcolors.rgb_to_hex(tuple([x * 255 for x in colorsys.hsv_to_rgb(
75 hsv[0], hsv[1], .2)])) 72 hsv[0], hsv[1], .2)]))
76 Frame.__init__(self, master, bd=1, relief='raised', bg=bg) 73 tk.Frame.__init__(self, master, bd=1, relief='raised', bg=bg)
77 self.name = sub.name 74 self.name = sub.name
78 self.slider_var = DoubleVar() 75 self.slider_var = tk.DoubleVar()
79 self.pauseTrace = False 76 self.pauseTrace = False
80 self.scale = SubScale(self, variable=self.slider_var, width=20) 77 self.scale = SubScale(self, variable=self.slider_var, width=20)
81 78
82 self.namelabel = Label(self, font="Arial 7", bg=darkBg, 79 self.namelabel = tk.Label(self, font="Arial 7", bg=darkBg,
83 fg='white', pady=0) 80 fg='white', pady=0)
84 self.sub.graph.addHandler(self.updateName) 81 self.sub.graph.addHandler(self.updateName)
85 82
86 self.namelabel.pack(side=TOP) 83 self.namelabel.pack(side=tk.TOP)
87 levellabel = Label(self, textvariable=self.slider_var, font="Arial 6", 84 levellabel = tk.Label(self, textvariable=self.slider_var, font="Arial 6",
88 bg='black', fg='white', pady=0) 85 bg='black', fg='white', pady=0)
89 levellabel.pack(side=TOP) 86 levellabel.pack(side=tk.TOP)
90 self.scale.pack(side=BOTTOM, expand=1, fill=BOTH) 87 self.scale.pack(side=tk.BOTTOM, expand=1, fill=tk.BOTH)
91 88
92 for w in [self, self.namelabel, levellabel]: 89 for w in [self, self.namelabel, levellabel]:
93 dragSourceRegister(w, 'copy', 'text/uri-list', sub.uri) 90 dragSourceRegister(w, 'copy', 'text/uri-list', sub.uri)
94 91
95 self._slider_var_trace = self.slider_var.trace('w', self.slider_changed) 92 self._slider_var_trace = self.slider_var.trace('w', self.slider_changed)
143 def updateName(self): 140 def updateName(self):
144 def shortUri(u): 141 def shortUri(u):
145 return '.../' + u.split('/')[-1] 142 return '.../' + u.split('/')[-1]
146 self.namelabel.config(text=self.sub.graph.label(self.sub.uri) or shortUri(self.sub.uri)) 143 self.namelabel.config(text=self.sub.graph.label(self.sub.uri) or shortUri(self.sub.uri))
147 144
148 class KeyboardComposer(Frame, SubClient): 145 class KeyboardComposer(tk.Frame, SubClient):
149 def __init__(self, root, graph, session, 146 def __init__(self, root, graph, session,
150 hw_sliders=True): 147 hw_sliders=True):
151 Frame.__init__(self, root, bg='black') 148 tk.Frame.__init__(self, root, bg='black')
152 SubClient.__init__(self) 149 SubClient.__init__(self)
153 self.graph = graph 150 self.graph = graph
154 self.session = session 151 self.session = session
155 self.submasters = Submasters(graph) 152 self.submasters = Submasters(graph)
156 self.subbox = {} # sub uri : SubmasterBox 153 self.subbox = {} # sub uri : SubmasterBox
168 self.graph.addHandler(self.redraw_sliders) 165 self.graph.addHandler(self.redraw_sliders)
169 self.send_levels_loop() 166 self.send_levels_loop()
170 self.graph.addHandler(self.rowFromGraph) 167 self.graph.addHandler(self.rowFromGraph)
171 168
172 def make_buttons(self): 169 def make_buttons(self):
173 self.buttonframe = Frame(self, bg='black') 170 self.buttonframe = tk.Frame(self, bg='black')
174 self.buttonframe.pack(side=BOTTOM) 171 self.buttonframe.pack(side=tk.BOTTOM)
175 172
176 self.sliders_status_var = IntVar() 173 self.sliders_status_var = tk.IntVar()
177 self.sliders_status_var.set(self.use_hw_sliders) 174 self.sliders_status_var.set(self.use_hw_sliders)
178 self.sliders_checkbutton = Checkbutton(self.buttonframe, 175 self.sliders_checkbutton = tk.Checkbutton(self.buttonframe,
179 text="Sliders", variable=self.sliders_status_var, 176 text="Sliders", variable=self.sliders_status_var,
180 command=lambda: self.toggle_slider_connectedness(), 177 command=lambda: self.toggle_slider_connectedness(),
181 bg='black', fg='white') 178 bg='black', fg='white')
182 self.sliders_checkbutton.pack(side=LEFT) 179 self.sliders_checkbutton.pack(side=tk.LEFT)
183 180
184 self.alltozerobutton = Button(self.buttonframe, text="All to Zero", 181 self.alltozerobutton = tk.Button(self.buttonframe, text="All to Zero",
185 command=self.alltozero, bg='black', fg='white') 182 command=self.alltozero, bg='black', fg='white')
186 self.alltozerobutton.pack(side='left') 183 self.alltozerobutton.pack(side='left')
187 184
188 self.save_stage_button = Button(self.buttonframe, text="Save", 185 self.save_stage_button = tk.Button(self.buttonframe, text="Save",
189 command=lambda: self.save_current_stage(self.sub_name.get()), 186 command=lambda: self.save_current_stage(self.sub_name.get()),
190 bg='black', fg='white') 187 bg='black', fg='white')
191 self.save_stage_button.pack(side=LEFT) 188 self.save_stage_button.pack(side=tk.LEFT)
192 self.sub_name = Entry(self.buttonframe, bg='black', fg='white') 189 self.sub_name = tk.Entry(self.buttonframe, bg='black', fg='white')
193 self.sub_name.pack(side=LEFT) 190 self.sub_name.pack(side=tk.LEFT)
194 191
195 def redraw_sliders(self): 192 def redraw_sliders(self):
196 self.draw_sliders() 193 self.draw_sliders()
197 if len(self.rows): 194 if len(self.rows):
198 self.change_row(self.current_row) 195 self.change_row(self.current_row)
228 sub.uri, 225 sub.uri,
229 sub) 226 sub)
230 for sub in self.submasters.get_all_subs()) 227 for sub in self.submasters.get_all_subs())
231 log.info("withgroups %s", withgroups) 228 log.info("withgroups %s", withgroups)
232 229
233 for group, order, _sortLabel, _sortUri, sub in withgroups: 230 for group, order, sortLabel, _sortUri, sub in withgroups:
234 group = self.graph.value(sub.uri, L9['group']) 231 group = self.graph.value(sub.uri, L9['group'])
235 232
236 if col == 0 or group != last_group: 233 if col == 0 or group != last_group:
237 row = self.make_row(group) 234 row = self.make_row(group)
238 rowcount += 1 235 rowcount += 1
268 dispatcher.connect(self.send_to_hw, 'send_to_hw') 265 dispatcher.connect(self.send_to_hw, 'send_to_hw')
269 else: 266 else:
270 self.sliders = DummySliders() 267 self.sliders = DummySliders()
271 268
272 def make_key_hints(self): 269 def make_key_hints(self):
273 keyhintrow = Frame(self) 270 keyhintrow = tk.Frame(self)
274 271
275 col = 0 272 col = 0
276 for upkey, downkey in zip(nudge_keys['up'], 273 for upkey, downkey in zip(nudge_keys['up'],
277 nudge_keys['down']): 274 nudge_keys['down']):
278 # what a hack! 275 # what a hack!
279 downkey = downkey.replace('semicolon', ';') 276 downkey = downkey.replace('semicolon', ';')
280 upkey, downkey = (upkey.upper(), downkey.upper()) 277 upkey, downkey = (upkey.upper(), downkey.upper())
281 278
282 # another what a hack! 279 # another what a hack!
283 keylabel = Label(keyhintrow, text='%s\n%s' % (upkey, downkey), 280 keylabel = tk.Label(keyhintrow, text='%s\n%s' % (upkey, downkey),
284 width=1, font=('Arial', 10), bg='red', fg='white', anchor='c') 281 width=1, font=('Arial', 10), bg='red', fg='white', anchor='c')
285 keylabel.pack(side=LEFT, expand=1, fill=X) 282 keylabel.pack(side=tk.LEFT, expand=1, fill=tk.X)
286 col += 1 283 col += 1
287 284
288 keyhintrow.pack(fill=X, expand=0) 285 keyhintrow.pack(fill=tk.X, expand=0)
289 self.keyhints = keyhintrow 286 self.keyhints = keyhintrow
290 287
291 def setup_key_nudgers(self, tkobject): 288 def setup_key_nudgers(self, tkobject):
292 for d, keys in nudge_keys.items(): 289 for d, keys in nudge_keys.items():
293 for key in keys: 290 for key in keys:
390 387
391 def send_to_hw(self, sub, hwCol, boxRow): 388 def send_to_hw(self, sub, hwCol, boxRow):
392 if isinstance(self.sliders, DummySliders): 389 if isinstance(self.sliders, DummySliders):
393 return 390 return
394 391
395 assert isinstance(sub, URIRef), repr(subUri) 392 assert isinstance(sub, URIRef), repr(sub)
396 393
397 if boxRow != self.current_row: 394 if boxRow != self.current_row:
398 return 395 return
399 396
400 try: 397 try:
413 return 410 return
414 self.sliders.valueOut(chan, v) 411 self.sliders.valueOut(chan, v)
415 412
416 def make_row(self, group): 413 def make_row(self, group):
417 """group is a URI or None""" 414 """group is a URI or None"""
418 row = Frame(self, bd=2, bg='black') 415 row = tk.Frame(self, bd=2, bg='black')
419 row.subGroup = group 416 row.subGroup = group
420 def onDrop(ev): 417 def onDrop(ev):
421 self.change_group(sub=URIRef(ev.data), row=row) 418 self.change_group(sub=URIRef(ev.data), row=row)
422 return "link" 419 return "link"
423 420
424 dropTargetRegister(row, onDrop=onDrop, typeList=['*'], 421 dropTargetRegister(row, onDrop=onDrop, typeList=['*'],
425 hoverStyle=dict(background="#555500")) 422 hoverStyle=dict(background="#555500"))
426 423
427 row.pack(expand=1, fill=BOTH) 424 row.pack(expand=1, fill=tk.BOTH)
428 self.setup_key_nudgers(row) 425 self.setup_key_nudgers(row)
429 self.rows.append(row) 426 self.rows.append(row)
430 return row 427 return row
431 428
432 def change_group(self, sub, row): 429 def change_group(self, sub, row):
545 def __init__(self, kc): 542 def __init__(self, kc):
546 devices = ['/dev/snd/midiC3D0', '/dev/snd/midiC2D0', '/dev/snd/midiC1D0'] 543 devices = ['/dev/snd/midiC3D0', '/dev/snd/midiC2D0', '/dev/snd/midiC1D0']
547 for dev in devices: 544 for dev in devices:
548 try: 545 try:
549 BCF2000.__init__(self, dev=dev) 546 BCF2000.__init__(self, dev=dev)
550 except IOError, e: 547 except IOError:
551 if dev is devices[-1]: 548 if dev is devices[-1]:
552 raise 549 raise
553 else: 550 else:
554 break 551 break
555 552
590 tl = toplevelat("Keyboard Composer - %s" % opts.session, 587 tl = toplevelat("Keyboard Composer - %s" % opts.session,
591 existingtoplevel=root, graph=graph, session=session) 588 existingtoplevel=root, graph=graph, session=session)
592 589
593 kc = KeyboardComposer(tl, graph, session, 590 kc = KeyboardComposer(tl, graph, session,
594 hw_sliders=not opts.no_sliders) 591 hw_sliders=not opts.no_sliders)
595 kc.pack(fill=BOTH, expand=1) 592 kc.pack(fill=tk.BOTH, expand=1)
596 593
597 for helpline in ["Bindings: B3 mute"]: 594 for helpline in ["Bindings: B3 mute"]:
598 tk.Label(root,text=helpline, font="Helvetica -12 italic", 595 tk.Label(root,text=helpline, font="Helvetica -12 italic",
599 anchor='w').pack(side='top',fill='x') 596 anchor='w').pack(side='top',fill='x')
600 597
611 graph = SyncedGraph(networking.rdfdb.url, "keyboardcomposer") 608 graph = SyncedGraph(networking.rdfdb.url, "keyboardcomposer")
612 609
613 # i think this also needs delayed start (like subcomposer has), to have a valid graph 610 # i think this also needs delayed start (like subcomposer has), to have a valid graph
614 # before setting any stuff from the ui 611 # before setting any stuff from the ui
615 612
616 root = Tk() 613 root = tk.Tk()
617 initTkdnd(root.tk, 'tkdnd/trunk/') 614 initTkdnd(root.tk, 'tkdnd/trunk/')
618 615
619 session = clientsession.getUri('keyboardcomposer', opts) 616 session = clientsession.getUri('keyboardcomposer', opts)
620 617
621 graph.initiallySynced.addCallback( 618 graph.initiallySynced.addCallback(