Changeset - 2848cf5e14c5
[Not reviewed]
default
0 2 0
David McClosky - 20 years ago 2005-06-18 01:37:23
dmcc@bigasterisk.com
keyboardcomposer: skip subs at 0 when combining, temporary subs don't listen for reloads
2 files changed with 2 insertions and 1 deletions:
0 comments (0 inline, 0 general)
bin/keyboardcomposer
Show inline comments
 
@@ -116,167 +116,167 @@ class KeyboardComposer(Frame, SubClient)
 
            col += 1
 

	
 
        keyhintrow.pack(fill=X, expand=0)
 
        self.keyhints = keyhintrow
 
    def setup_key_nudgers(self, tkobject):
 
        for d, keys in nudge_keys.items():
 
            for key in keys:
 
                # lowercase makes full=0
 
                keysym = "<KeyPress-%s>" % key
 
                tkobject.bind(keysym, \
 
                    lambda evt, num=keys.index(key), d=d: \
 
                        self.got_nudger(num, d))
 

	
 
                # uppercase makes full=1
 
                keysym = "<KeyPress-%s>" % key.upper()
 
                keysym = keysym.replace('SEMICOLON', 'colon')
 
                tkobject.bind(keysym, \
 
                    lambda evt, num=keys.index(key), d=d: \
 
                        self.got_nudger(num, d, full=1))
 

	
 
        # Row changing:
 
        # Page dn, C-n, and ] do down
 
        # Page up, C-p, and ' do up
 
        for key in '<Prior> <Next> <Control-n> <Control-p> ' \
 
                   '<Key-bracketright> <Key-apostrophe>'.split():
 
            tkobject.bind(key, self.change_row)
 

	
 
    def change_row(self, event):
 
        diff = 1
 
        if event.keysym in ('Prior', 'p', 'bracketright'):
 
            diff = -1
 
        old_row = self.current_row
 
        self.current_row += diff
 
        self.current_row = max(0, self.current_row)
 
        self.current_row = min(len(self.rows) - 1, self.current_row)
 
        self.unhighlight_row(old_row)
 
        self.highlight_row(self.current_row)
 
        row = self.rows[self.current_row]
 
        self.keyhints.pack_configure(before=row)
 
    def got_nudger(self, number, direction, full=0):
 
        subtk = self.slider_table[(self.current_row, number)]
 
        if direction == 'up':
 
            if full:
 
                subtk.scale.fade(1)
 
            else:
 
                subtk.scale.increase()
 
        else:
 
            if full:
 
                subtk.scale.fade(0)
 
            else:
 
                subtk.scale.decrease()
 
    def draw_sliders(self):
 
        self.tk_focusFollowsMouse()
 

	
 
        rowcount = -1
 
        col = 0
 
        for sub in self.submasters.get_all_subs():
 
            if col == 0: # make new row
 
                row = self.make_row()
 
                rowcount += 1
 
            current_level = self.current_sub_levels.get(sub.name, 0)
 
            subtk = self.draw_sub_slider(row, col, sub.name, current_level)
 
            self.slider_table[(rowcount, col)] = subtk
 
            self.name_to_subtk[sub.name] = subtk
 
            col += 1
 
            col %= 10
 

	
 
            def slider_changed(x, y, z, subtk=subtk):
 
                subtk.scale.draw_indicator_colors()
 
                self.send_levels()
 

	
 
            subtk.slider_var.trace('w', slider_changed)
 
    def make_row(self):
 
        row = Frame(self, bd=2, bg='black')
 
        row.pack(expand=1, fill=BOTH)
 
        self.setup_key_nudgers(row)
 
        self.rows.append(row)
 
        return row
 
    def draw_sub_slider(self, row, col, name, current_level):
 
        subtk = SubmasterTk(row, name, current_level)
 
        subtk.place(relx=col * 0.1, rely=0, relwidth=0.1, relheight=1)
 
        self.setup_key_nudgers(subtk.scale)
 

	
 
        self.slider_vars[name] = subtk.slider_var
 
        return subtk
 
    def highlight_row(self, row):
 
        row = self.rows[row]
 
        row['bg'] = 'red'
 
    def unhighlight_row(self, row):
 
        row = self.rows[row]
 
        row['bg'] = 'black'
 
    def get_levels(self):
 
        return dict([(name, slidervar.get()) 
 
            for name, slidervar in self.slider_vars.items()])
 
    def get_levels_as_sub(self):
 
        scaledsubs = [self.submasters.get_sub_by_name(sub) * level \
 
            for sub, level in self.get_levels().items()]
 
            for sub, level in self.get_levels().items() if level > 0.0]
 

	
 
        maxes = sub_maxes(*scaledsubs)
 
        return maxes
 
    def save_current_stage(self, subname):
 
        print "saving current levels as", subname
 
        sub = self.get_levels_as_sub()
 
        sub.name = subname
 
        sub.temporary = 0
 
        sub.save()
 

	
 
    def save(self):
 
        pickle.dump(self.get_levels(), 
 
                    file('.keyboardcomposer.savedlevels', 'w'))
 
    def send_frequent_updates(self):
 
        """called when we get a fade -- send events as quickly as possible"""
 
        if time.time() <= self.stop_frequent_update_time:
 
            self.send_levels()
 
            self.after(10, self.send_frequent_updates)
 

	
 
    def refresh(self):
 
        self.save()
 
        self.submasters = Submasters()
 
        self.current_sub_levels = \
 
            pickle.load(file('.keyboardcomposer.savedlevels'))
 
        for r in self.rows:
 
            r.destroy()
 
        self.keyhints.destroy()
 
        self.buttonframe.destroy()
 
        self.draw_ui()
 

	
 
    def alltozero(self):
 
        for name, subtk in self.name_to_subtk.items():
 
            if subtk.scale.scale_var.get() != 0:
 
                subtk.scale.fade(value=0.0, length=0)
 

	
 
class LevelServer(xmlrpc.XMLRPC):
 
    def __init__(self,name_to_subtk):
 
        self.name_to_subtk = name_to_subtk
 
        
 
    def xmlrpc_fadesub(self,subname,level,secs):
 
        """submaster will fade to level in secs"""
 
        try:
 
            self.name_to_subtk[subname].scale.fade(level,secs)
 
            ret='ok'
 
        except Exception,e:
 
            ret=str(e)
 
        return ret
 

	
 
if __name__ == "__main__":
 
    s = Submasters()
 

	
 
    root = Tk()
 
    tl = toplevelat("Keyboard Composer", existingtoplevel=root)
 

	
 
    kc = KeyboardComposer(tl, s)
 
    kc.pack(fill=BOTH, expand=1)
 

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

	
 
    root.protocol('WM_DELETE_WINDOW', reactor.stop)
 
    reactor.addSystemEventTrigger('after', 'shutdown', kc.save)
 
    
 
    tksupport.install(root,ms=10)
 
    reactor.run()
light9/Submaster.py
Show inline comments
 
from __future__ import division
 
import os
 
from light9.TLUtility import dict_scale, dict_max
 
from light9 import Patch, showconfig
 
import dispatch.dispatcher as dispatcher
 

	
 
class Submaster:
 
    "Contain a dictionary of levels, but you didn't need to know that"
 
    def __init__(self, name, leveldict=None, temporary=0):
 
        self.name = name
 
        self.temporary = temporary
 
        if leveldict:
 
            self.levels = leveldict
 
        else:
 
            self.levels = {}
 
            self.reload(quiet=True)
 
        if not self.temporary:
 
        dispatcher.connect(self.reload, 'reload all subs')
 
    def reload(self, quiet=False):
 
        if self.temporary:
 
            return
 
        try:
 
            oldlevels = self.levels.copy()
 
            self.levels.clear()
 
            subfile = file(showconfig.subFile(self.name))
 
            for line in subfile.readlines():
 
                if not line.strip(): # if line is only whitespace
 
                    continue # "did i say newspace?"
 

	
 
                try:
 
                    name, val = line.split(':')
 
                    name = name.strip()
 
                    self.levels[name] = float(val)
 
                except ValueError:
 
                    print "(%s) Error with this line: %s" % (self.name, 
 
                        line[:-1])
 

	
 
                if (not quiet) and (oldlevels != self.levels):
 
                    print "sub %s changed" % self.name
 
        except IOError:
 
            print "Can't read file for sub: %s" % self.name
 
    def save(self):
 
        if self.temporary:
 
            print "not saving temporary sub named",self.name
 
            return
 

	
 
        subfile = file(showconfig.subFile(self.name), 'w')
 
        names = self.levels.keys()
 
        names.sort()
 
        for name in names:
 
            val = self.levels[name]
 
            subfile.write("%s : %s\n" % (name, val))
 
    def set_level(self, channelname, level, save=1):
 
        self.levels[Patch.resolve_name(channelname)] = level
 
        if save:
 
            self.save()
 
    def set_all_levels(self, leveldict):
 
        self.levels.clear()
 
        for k, v in leveldict.items():
 
            self.set_level(k, v, save=0)
 
        self.save()
 
    def get_levels(self):
 
        return self.levels
 
    def no_nonzero(self):
 
        return (not self.levels.values()) or not (max(self.levels.values()) > 0)
 
    def __mul__(self, scalar):
 
        return Submaster("%s*%s" % (self.name, scalar), 
 
            dict_scale(self.levels, scalar), temporary=1)
 
    __rmul__ = __mul__
 
    def max(self, *othersubs):
 
        return sub_maxes(self, *othersubs)
 
    def __repr__(self):
 
        items = self.levels.items()
 
        items.sort()
 
        levels = ' '.join(["%s:%.2f" % item for item in items])
 
        return "<'%s': [%s]>" % (self.name, levels)
 
    def get_dmx_list(self):
 
        leveldict = self.get_levels() # gets levels of sub contents
 

	
 
        levels = [0] * 68
 
        for k, v in leveldict.items():
 
            if v == 0:
 
                continue
 
            try:
 
                dmxchan = Patch.get_dmx_channel(k) - 1
 
            except ValueError:
 
                print "error trying to compute dmx levels for submaster %s" % self.name
 
                raise
 
            levels[dmxchan] = max(v, levels[dmxchan])
 

	
 
        return levels
 
    def normalize_patch_names(self):
 
        """Use only the primary patch names."""
 
        # possibly busted -- don't use unless you know what you're doing
 
        self.set_all_levels(self.levels.copy())
 
    def get_normalized_copy(self):
 
        """Get a copy of this sumbaster that only uses the primary patch 
 
        names.  The levels will be the same."""
 
        newsub = Submaster("%s (normalized)" % self.name, temporary=1)
 
        newsub.set_all_levels(self.levels)
 
        return newsub
 
    def crossfade(self, othersub, amount):
 
        """Returns a new sub that is a crossfade between this sub and
 
        another submaster.  
 
        
 
        NOTE: You should only crossfade between normalized submasters."""
 
        otherlevels = othersub.get_levels()
 
        keys_set = {}
 
        for k in self.levels.keys() + otherlevels.keys():
 
            keys_set[k] = 1
 
        all_keys = keys_set.keys()
 

	
 
        xfaded_sub = Submaster("xfade", temporary=1)
0 comments (0 inline, 0 general)