Changeset - d230824728aa
[Not reviewed]
default
0 1 1
Drew Perttula - 13 years ago 2012-06-15 06:09:49
drewp@bigasterisk.com
drag submasters out of keyboardcomposer
Ignore-this: cbc405d57f6727db9690e527681202f3
2 files changed with 35 insertions and 0 deletions:
0 comments (0 inline, 0 general)
bin/keyboardcomposer
Show inline comments
 
#!bin/python
 

	
 
from __future__ import division, nested_scopes
 
import cgi, os, sys, time, subprocess, logging
 
from optparse import OptionParser
 
import webcolors, colorsys
 

	
 
from twisted.internet import reactor, tksupport
 
from twisted.web import xmlrpc, server, resource
 
from Tix import *
 
import Tix as tk
 
import pickle
 

	
 
import run_local
 
from light9.Fadable import Fadable
 
from light9.Submaster import Submasters, sub_maxes
 
from light9.subclient import SubClient
 
from light9 import dmxclient, showconfig, networking, prof
 
from light9.uihelpers import toplevelat, bindkeys
 
from light9.namespaces import L9
 
from light9.tkdnd import initTkdnd, dragSourceRegister
 
from bcf2000 import BCF2000
 

	
 
nudge_keys = {
 
    'up'   : list('qwertyui'),
 
    'down' : list('asdfghjk')
 
}
 

	
 
class DummySliders:
 
    def valueOut(self, name, value):
 
        pass
 
    def close(self):
 
        pass
 
    def reopen(self):
 
        pass
 

	
 
class SubScale(Scale, Fadable):
 
    def __init__(self, master, *args, **kw):
 
        self.scale_var = kw.get('variable') or DoubleVar()
 
        kw.update({'variable' : self.scale_var,
 
                   'from' : 1, 'to' : 0, 'showvalue' : 0,
 
                   'sliderlength' : 15, 'res' : 0.01,
 
                   'width' : 40, 'troughcolor' : 'black', 'bg' : 'grey40',
 
                   'highlightthickness' : 1, 'bd' : 1,
 
                   'highlightcolor' : 'red', 'highlightbackground' : 'black',
 
@@ -52,48 +53,51 @@ class SubScale(Scale, Fadable):
 
        else:
 
            self['troughcolor'] = 'blue'
 

	
 
class SubmasterTk(Frame):
 
    def __init__(self, master, sub, current_level):
 
        bg = sub.graph.value(sub.uri, L9.color, default='#000000')
 
        rgb = webcolors.hex_to_rgb(bg)
 
        hsv = colorsys.rgb_to_hsv(*[x/255 for x in rgb])
 
        darkBg = webcolors.rgb_to_hex(tuple([x * 255 for x in colorsys.hsv_to_rgb(
 
            hsv[0], hsv[1], .3)]))
 
        Frame.__init__(self, master, bd=1, relief='raised', bg=bg)
 
        self.name = sub.name
 
        self.slider_var = DoubleVar()
 
        self.slider_var.set(current_level)
 
        self.scale = SubScale(self, variable=self.slider_var, width=20)
 
        namelabel = Label(self, text=sub.name, font="Arial 7", bg=darkBg,
 
            fg='white', pady=0)
 
        namelabel.pack(side=TOP)
 
        levellabel = Label(self, textvariable=self.slider_var, font="Arial 7",
 
            bg='black', fg='white', pady=0)
 
        levellabel.pack(side=TOP)
 
        self.scale.pack(side=BOTTOM, expand=1, fill=BOTH)
 
        bindkeys(self, "<Control-Key-l>", self.launch_subcomposer)
 

	
 
        for w in [self, namelabel, levellabel]:
 
            dragSourceRegister(w, 'copy', 'text/uri-list', sub.uri)
 

	
 
    def launch_subcomposer(self, *args):
 
        subprocess.Popen(["bin/subcomposer", "--no-geometry", self.name])
 

	
 
class KeyboardComposer(Frame, SubClient):
 
    def __init__(self, root, graph, submasters, current_sub_levels=None,
 
                 hw_sliders=True):
 
        Frame.__init__(self, root, bg='black')
 
        SubClient.__init__(self)
 
        self.graph = graph
 
        self.submasters = submasters
 
        self.name_to_subtk = {}
 
        self.current_sub_levels = {}
 
        self.current_row = 0
 
        if current_sub_levels is not None:
 
            self.current_sub_levels = current_sub_levels
 
        else:
 
            try:
 
                self.current_sub_levels, self.current_row = \
 
                    pickle.load(file('.keyboardcomposer.savedlevels'))
 
            except IOError:
 
                pass
 

	
 
        self.use_hw_sliders = hw_sliders
 
        self.connect_to_hw(hw_sliders)
 
@@ -444,48 +448,50 @@ class Sliders(BCF2000):
 
            elif button_num == 3:
 
                diff = 1
 
            else:
 
                return
 

	
 
            kc.change_row(kc.current_row + diff)
 
            self.valueOut(name, 0)
 

	
 
if __name__ == "__main__":
 
    parser = OptionParser()
 
    parser.add_option('--nonpersistent', action="store_true",
 
                      help="don't load or save levels")
 
    parser.add_option('--no-sliders', action='store_true',
 
                      help="don't attach to hardware sliders")
 
    parser.add_option('-v', action='store_true', help="log info level")
 
    opts, args = parser.parse_args()
 

	
 
    logging.basicConfig(level=logging.INFO if opts.v else logging.WARN)
 
    log = logging.getLogger()
 

	
 
    graph = showconfig.getGraph()
 
    s = Submasters(graph)
 

	
 
    root = Tk()
 
    initTkdnd(root.tk, 'tkdnd/trunk/')
 
    
 
    tl = toplevelat("Keyboard Composer", existingtoplevel=root)
 

	
 
    startLevels = None
 
    if opts.nonpersistent:
 
        startLevels = {}
 
    kc = KeyboardComposer(tl, graph, s, startLevels,
 
                          hw_sliders=not opts.no_sliders)
 
    kc.pack(fill=BOTH, expand=1)
 

	
 
    for helpline in ["Bindings: B3 mute; C-l edit levels in subcomposer"]:
 
        tk.Label(root,text=helpline, font="Helvetica -12 italic",
 
                 anchor='w').pack(side='top',fill='x')
 

	
 
    import twisted.internet
 
    try:
 
        reactor.listenTCP(networking.keyboardComposer.port,
 
                          server.Site(LevelServerHttp(kc.name_to_subtk)))
 
    except twisted.internet.error.CannotListenError, e:
 
        print "Can't (and won't!) start level server:"
 
        print e
 

	
 
    root.protocol('WM_DELETE_WINDOW', reactor.stop)
 
    if not opts.nonpersistent:
 
        reactor.addSystemEventTrigger('after', 'shutdown', kc.save)
light9/tkdnd.py
Show inline comments
 
new file 100644
 
from glob import glob
 
from os.path import join, basename
 

	
 
def initTkdnd(tk, tkdndBuildDir):
 
    """
 
    pass the 'tk' attribute of any Tkinter object, and the top dir of
 
    your built tkdnd package
 
    """
 
    tk.call('source', join(tkdndBuildDir, 'library/tkdnd.tcl'))
 
    for dll in glob(join(tkdndBuildDir,
 
                         '*tkdnd*' + tk.call('info', 'sharedlibextension'))):
 
        tk.call('tkdnd::initialise',
 
                join(tkdndBuildDir, 'library'),
 
                join('..', basename(dll)),
 
                'tkdnd')
 

	
 
def dragSourceRegister(widget,
 
                       action='copy', datatype='text/uri-list', data=''):
 
    widget.tk.call('tkdnd::drag_source', 'register', widget._w)
 

	
 
    # with normal Tkinter bind(), the result of your handler isn't
 
    # actually returned so the drag doesn't get launched. This is a
 
    # corrected version of what bind() does when you pass a function,
 
    # but I don't block my tuple from getting returned (as a tcl list)
 
    funcId = widget._register(lambda: (action, datatype, data),
 
                              widget._substitute,
 
                              1 # needscleanup
 
                              )
 
    widget.bind("<<DragInitCmd>>", funcId)
0 comments (0 inline, 0 general)