Changeset - 1aa91a31c0e2
[Not reviewed]
default
0 13 0
Drew Perttula - 6 years ago 2019-05-25 12:06:01
drewp@bigasterisk.com
reformat some missed files
Ignore-this: f13152975437adeb48ed619ab676365e
13 files changed with 270 insertions and 176 deletions:
0 comments (0 inline, 0 general)
bin/run_local.py
Show inline comments
 
@@ -17,12 +17,12 @@ def fixSysPath():
 
        root + 'env/lib/python3.7/lib-dynload',
 
        '/usr/lib/python3/dist-packages/',
 
        '/usr/lib/python3.7',
 
#        '/usr/lib/python3.7/plat-x86_64-linux-gnu',
 
#        '/usr/lib/python3.7/lib-tk',
 
#        root + 'env/local/lib/python3.7/site-packages',
 
#        root + 'env/local/lib/python3.7/site-packages/gtk-2.0',
 
        #        '/usr/lib/python3.7/plat-x86_64-linux-gnu',
 
        #        '/usr/lib/python3.7/lib-tk',
 
        #        root + 'env/local/lib/python3.7/site-packages',
 
        #        root + 'env/local/lib/python3.7/site-packages/gtk-2.0',
 
        root + 'env/lib/python3.7/site-packages',
 
#        root + 'env/lib/python3.7/site-packages/gtk-2.0',
 
        #        root + 'env/lib/python3.7/site-packages/gtk-2.0',
 
    ]
 

	
 

	
light9/Effects.py
Show inline comments
 

	
 
import random as random_mod
 
import math
 
import logging, colorsys
light9/FlyingFader.py
Show inline comments
 
@@ -2,7 +2,6 @@ from tkinter.tix import *
 
from time import time, sleep
 

	
 

	
 

	
 
class Mass:
 

	
 
    def __init__(self):
light9/Submaster.py
Show inline comments
 

	
 
import os, logging, time
 
from rdflib import Graph, RDF
 
from rdflib import RDFS, Literal, BNode
 
@@ -10,8 +9,10 @@ from louie import dispatcher
 
from .rdfdb.patch import Patch
 
log = logging.getLogger('submaster')
 

	
 

	
 
class Submaster(object):
 
    """mapping of channels to levels"""
 

	
 
    def __init__(self, name, levels):
 
        """this sub has a name just for debugging. It doesn't get persisted.
 
        See PersistentSubmaster.
 
@@ -51,7 +52,9 @@ class Submaster(object):
 
    def __mul__(self, scalar):
 
        return Submaster("%s*%s" % (self.name, scalar),
 
                         levels=dict_scale(self.levels, scalar))
 

	
 
    __rmul__ = __mul__
 

	
 
    def max(self, *othersubs):
 
        return sub_maxes(self, *othersubs)
 

	
 
@@ -76,7 +79,7 @@ class Submaster(object):
 
        return hash(self.ident())
 

	
 
    def get_dmx_list(self):
 
        leveldict = self.get_levels() # gets levels of sub contents
 
        leveldict = self.get_levels()  # gets levels of sub contents
 

	
 
        levels = []
 
        for k, v in list(leveldict.items()):
 
@@ -85,8 +88,9 @@ class Submaster(object):
 
            try:
 
                dmxchan = get_dmx_channel(k) - 1
 
            except ValueError:
 
                log.error("error trying to compute dmx levels for submaster %s"
 
                          % self.name)
 
                log.error(
 
                    "error trying to compute dmx levels for submaster %s" %
 
                    self.name)
 
                raise
 
            if dmxchan >= len(levels):
 
                levels.extend([0] * (dmxchan - len(levels) + 1))
 
@@ -119,14 +123,16 @@ class Submaster(object):
 

	
 
        xfaded_sub = Submaster("xfade", {})
 
        for k in all_keys:
 
            xfaded_sub.set_level(k,
 
                                 linear_fade(self.levels.get(k, 0),
 
                                             otherlevels.get(k, 0),
 
                                             amount))
 
            xfaded_sub.set_level(
 
                k,
 
                linear_fade(self.levels.get(k, 0), otherlevels.get(k, 0),
 
                            amount))
 

	
 
        return xfaded_sub
 

	
 

	
 
class PersistentSubmaster(Submaster):
 

	
 
    def __init__(self, graph, uri):
 
        if uri is None:
 
            raise TypeError("uri must be URIRef")
 
@@ -144,7 +150,7 @@ class PersistentSubmaster(Submaster):
 

	
 
    def changeName(self, newName):
 
        self.graph.patchObject(self.uri, self.uri, RDFS.label, Literal(newName))
 
        
 

	
 
    def setName(self):
 
        log.info("sub update name %s %s", self.uri, self.graph.label(self.uri))
 
        self.name = self.graph.label(self.uri)
 
@@ -193,23 +199,27 @@ class PersistentSubmaster(Submaster):
 
        typeStmt = (self.uri, RDF.type, L9['Submaster'])
 
        with self.graph.currentState(tripleFilter=typeStmt) as current:
 
            try:
 
                log.debug("submaster's type statement is in %r so we save there" %
 
                          list(current.contextsForStatement(typeStmt)))
 
                log.debug(
 
                    "submaster's type statement is in %r so we save there" %
 
                    list(current.contextsForStatement(typeStmt)))
 
                ctx = current.contextsForStatement(typeStmt)[0]
 
            except IndexError:
 
                log.info("declaring %s to be a submaster" % self.uri)
 
                ctx = self.uri
 
                self.graph.patch(Patch(addQuads=[
 
                    (self.uri, RDF.type, L9['Submaster'], ctx),
 
                self.graph.patch(
 
                    Patch(addQuads=[
 
                        (self.uri, RDF.type, L9['Submaster'], ctx),
 
                    ]))
 

	
 
        return ctx
 

	
 
    def editLevel(self, chan, newLevel):
 
        self.graph.patchMapping(self._saveContext(),
 
                                subject=self.uri, predicate=L9['lightLevel'],
 
                                subject=self.uri,
 
                                predicate=L9['lightLevel'],
 
                                nodeClass=L9['ChannelSetting'],
 
                                keyPred=L9['channel'], newKey=chan,
 
                                keyPred=L9['channel'],
 
                                newKey=chan,
 
                                valuePred=L9['level'],
 
                                newValue=Literal(newLevel))
 

	
 
@@ -225,16 +235,15 @@ class PersistentSubmaster(Submaster):
 
        quads = []
 
        with self.graph.currentState() as current:
 
            quads.extend(current.quads((self.uri, None, None)))
 
            for s,p,o,c in quads:
 
            for s, p, o, c in quads:
 
                if p == L9['lightLevel']:
 
                    quads.extend(current.quads((o, None, None)))
 
        return quads
 

	
 

	
 
    def save(self):
 
        raise NotImplementedError("obsolete?")
 
        if self.temporary:
 
            log.info("not saving temporary sub named %s",self.name)
 
            log.info("not saving temporary sub named %s", self.name)
 
            return
 

	
 
        graph = Graph()
 
@@ -265,12 +274,14 @@ def linear_fade(start, end, amount):
 
    level = start + (amount * (end - start))
 
    return level
 

	
 

	
 
def sub_maxes(*subs):
 
    nonzero_subs = [s for s in subs if not s.no_nonzero()]
 
    name = "max(%s)" % ", ".join([repr(s) for s in nonzero_subs])
 
    return Submaster(name,
 
                     levels=dict_max(*[sub.levels for sub in nonzero_subs]))
 

	
 

	
 
def combine_subdict(subdict, name=None, permanent=False):
 
    """A subdict is { Submaster objects : levels }.  We combine all
 
    submasters first by multiplying the submasters by their corresponding
 
@@ -287,10 +298,12 @@ def combine_subdict(subdict, name=None, 
 

	
 
    return maxes
 

	
 

	
 
class Submasters(object):
 
    "Collection o' Submaster objects"
 

	
 
    def __init__(self, graph):
 
        self.submasters = {} # uri : Submaster
 
        self.submasters = {}  # uri : Submaster
 
        self.graph = graph
 

	
 
        graph.addHandler(self.findSubs)
 
@@ -332,9 +345,11 @@ class Submasters(object):
 
    def get_sub_by_name(self, name):
 
        return get_sub_by_name(name, self)
 

	
 

	
 
# a global instance of Submasters, created on demand
 
_submasters = None
 

	
 

	
 
def get_global_submasters(graph):
 
    """
 
    Get (and make on demand) the global instance of
 
@@ -346,6 +361,7 @@ def get_global_submasters(graph):
 
        _submasters = Submasters(graph)
 
    return _submasters
 

	
 

	
 
def get_sub_by_name(name, submasters=None):
 
    """name is a channel or sub nama, submasters is a Submasters object.
 
    If you leave submasters empty, it will use the global instance of
 
@@ -359,14 +375,14 @@ def get_sub_by_name(name, submasters=Non
 

	
 
    try:
 
        val = int(name)
 
        s = Submaster("#%d" % val, levels={val : 1.0})
 
        s = Submaster("#%d" % val, levels={val: 1.0})
 
        return s
 
    except ValueError:
 
        pass
 

	
 
    try:
 
        subnum = get_dmx_channel(name)
 
        s = Submaster("'%s'" % name, levels={subnum : 1.0})
 
        s = Submaster("'%s'" % name, levels={subnum: 1.0})
 
        return s
 
    except ValueError:
 
        pass
light9/TLUtility.py
Show inline comments
 
"""Collected utility functions, many are taken from Drew's utils.py in
 
Cuisine CVS and Hiss's Utility.py."""
 

	
 

	
 
import sys
 

	
 
__author__ = "David McClosky <dmcc@bigasterisk.com>, " + \
 
             "Drew Perttula <drewp@bigasterisk.com>"
 
__cvsid__ = "$Id: TLUtility.py,v 1.1 2003/05/25 08:25:35 dmcc Exp $"
 
__version__ = "$Revision: 1.1 $"[11:-2]
 
__version__ = "$Revision: 1.1 $" [11:-2]
 

	
 

	
 
def make_attributes_from_args(*argnames):
 
    """
 
@@ -25,15 +25,16 @@ def make_attributes_from_args(*argnames)
 
            self.baz=baz
 
            ... 
 
    """
 
    
 
    callerlocals=sys._getframe(1).f_locals
 
    callerself=callerlocals['self']
 

	
 
    callerlocals = sys._getframe(1).f_locals
 
    callerself = callerlocals['self']
 
    for a in argnames:
 
        try:
 
            setattr(callerself,a,callerlocals[a])
 
            setattr(callerself, a, callerlocals[a])
 
        except KeyError:
 
            raise KeyError("Function has no argument '%s'" % a)
 

	
 

	
 
def enumerate(*collections):
 
    """Generates an indexed series:  (0,coll[0]), (1,coll[1]) ...
 
    
 
@@ -43,9 +44,12 @@ def enumerate(*collections):
 
    i = 0
 
    iters = [iter(collection) for collection in collections]
 
    while True:
 
        yield [i,] + [next(iterator) for iterator in iters]
 
        yield [
 
            i,
 
        ] + [next(iterator) for iterator in iters]
 
        i += 1
 

	
 

	
 
def dumpobj(o):
 
    """Prints all the object's non-callable attributes"""
 
    print(repr(o))
 
@@ -56,6 +60,7 @@ def dumpobj(o):
 
            pass
 
    print("")
 

	
 

	
 
def dict_filter_update(d, **newitems):
 
    """Adds a set of new keys and values to dictionary 'd' if the values are
 
    true:
 
@@ -68,6 +73,7 @@ def dict_filter_update(d, **newitems):
 
    for k, v in list(newitems.items()):
 
        if v: d[k] = v
 

	
 

	
 
def try_get_logger(channel):
 
    """Tries to get a logger with the channel 'channel'.  Will return a
 
    silent DummyClass if logging is not available."""
 
@@ -78,6 +84,7 @@ def try_get_logger(channel):
 
        log = DummyClass()
 
    return log
 

	
 

	
 
class DummyClass:
 
    """A class that can be instantiated but never used.  It is intended to
 
    be replaced when information is available.
 
@@ -96,9 +103,11 @@ class DummyClass:
 
      File "Utility.py", line 33, in __getattr__
 
        raise AttributeError, "Attempted usage of a DummyClass: %s" % key
 
    AttributeError: Attempted usage of a DummyClass: somefunction"""
 

	
 
    def __init__(self, use_warnings=1, raise_exceptions=0, **kw):
 
        """Constructs a DummyClass"""
 
        make_attributes_from_args('use_warnings', 'raise_exceptions')
 

	
 
    def __getattr__(self, key):
 
        """Raises an exception to warn the user that a Dummy is not being
 
        replaced in time."""
 
@@ -111,21 +120,27 @@ class DummyClass:
 
        if self.raise_exceptions:
 
            raise AttributeError(msg)
 
        return lambda *args, **kw: self.bogus_function()
 

	
 
    def bogus_function(self):
 
        pass
 

	
 

	
 
class ClassyDict(dict):
 
    """A dict that accepts attribute-style access as well (for keys
 
    that are legal names, obviously). I used to call this Struct, but
 
    chose the more colorful name to avoid confusion with the struct
 
    module."""
 

	
 
    def __getattr__(self, a):
 
        return self[a]
 

	
 
    def __setattr__(self, a, v):
 
        self[a] = v
 

	
 
    def __delattr__(self, a):
 
        del self[a]
 

	
 

	
 
def trace(func):
 
    """Good old fashioned Lisp-style tracing.  Example usage:
 
    
 
@@ -145,6 +160,7 @@ def trace(func):
 
          indent for recursive call like the lisp version (possible use of 
 
              generators?)"""
 
    name = func.__name__
 

	
 
    def tracer(*args, **kw):
 
        s = '|>> %s called' % name
 
        if args:
 
@@ -155,8 +171,10 @@ def trace(func):
 
        ret = func(*args, **kw)
 
        print('<<| %s returned %s' % (name, ret))
 
        return ret
 

	
 
    return tracer
 

	
 

	
 
# these functions taken from old light8 code
 
def dict_max(*dicts):
 
    """
 
@@ -165,22 +183,25 @@ def dict_max(*dicts):
 
    """
 
    newdict = {}
 
    for d in dicts:
 
        for k,v in list(d.items()):
 
        for k, v in list(d.items()):
 
            newdict[k] = max(v, newdict.get(k, 0))
 
    return newdict
 

	
 
def dict_scale(d,scl):
 

	
 
def dict_scale(d, scl):
 
    """scales all values in dict and returns a new dict"""
 
    return dict([(k,v*scl) for k,v in list(d.items())])
 
    
 
    return dict([(k, v * scl) for k, v in list(d.items())])
 

	
 

	
 
def dict_subset(d, dkeys, default=0):
 
    """Subset of dictionary d: only the keys in dkeys.  If you plan on omitting
 
    keys, make sure you like the default."""
 
    newd = {} # dirty variables!
 
    newd = {}  # dirty variables!
 
    for k in dkeys:
 
        newd[k] = d.get(k, default)
 
    return newd
 

	
 

	
 
# functions specific to Timeline
 
# TBD
 
def last_less_than(array, x):
 
@@ -193,6 +214,7 @@ def last_less_than(array, x):
 
            return best
 
    return best
 

	
 

	
 
# TBD
 
def first_greater_than(array, x):
 
    """array must be sorted"""
 
@@ -205,5 +227,3 @@ def first_greater_than(array, x):
 
        elif best is not None:
 
            return best
 
    return best
 

	
 

	
light9/chase.py
Show inline comments
 

	
 

	
 

	
 
def chase(t,
 
          ontime=0.5,
 
          offset=0.2,
light9/showconfig.py
Show inline comments
 
@@ -6,21 +6,27 @@ from rdflib import URIRef
 
from .namespaces import MUS, L9
 
log = logging.getLogger('showconfig')
 

	
 
_config = None # graph
 
_config = None  # graph
 

	
 

	
 
def getGraph():
 
    warnings.warn("code that's using showconfig.getGraph should be "
 
                  "converted to use the sync graph", stacklevel=2)
 
    warnings.warn(
 
        "code that's using showconfig.getGraph should be "
 
        "converted to use the sync graph",
 
        stacklevel=2)
 
    global _config
 
    if _config is None:
 
        graph = Graph()
 
        # note that logging is probably not configured the first time
 
        # we're in here
 
        warnings.warn("reading n3 files around %r" % root())
 
        for f in FilePath(root()).globChildren("*.n3") + FilePath(root()).globChildren("build/*.n3"):
 
        for f in FilePath(root()).globChildren("*.n3") + FilePath(
 
                root()).globChildren("build/*.n3"):
 
            graph.parse(location=f.path, format='n3')
 
        _config = graph
 
    return _config
 

	
 

	
 
def root():
 
    r = getenv("LIGHT9_SHOW")
 
    if r is None:
 
@@ -28,7 +34,10 @@ def root():
 
            "LIGHT9_SHOW env variable has not been set to the show root")
 
    return r
 

	
 

	
 
_showUri = None
 

	
 

	
 
def showUri():
 
    """Return the show URI associated with $LIGHT9_SHOW."""
 
    global _showUri
 
@@ -36,6 +45,7 @@ def showUri():
 
        _showUri = URIRef(open(path.join(root(), 'URI')).read().strip())
 
    return _showUri
 

	
 

	
 
def songOnDisk(song):
 
    """given a song URI, where's the on-disk file that mpd would read?"""
 
    graph = getGraph()
 
@@ -49,6 +59,7 @@ def songOnDisk(song):
 

	
 
    return path.abspath(path.join(root, name))
 

	
 

	
 
def songFilenameFromURI(uri):
 
    """
 
    'http://light9.bigasterisk.com/show/dance2007/song8' -> 'song8'
 
@@ -58,6 +69,7 @@ def songFilenameFromURI(uri):
 
    assert isinstance(uri, URIRef)
 
    return uri.split('/')[-1]
 

	
 

	
 
def getSongsFromShow(graph, show):
 
    playList = graph.value(show, L9['playList'])
 
    if not playList:
 
@@ -68,11 +80,14 @@ def getSongsFromShow(graph, show):
 

	
 
    return songs
 

	
 

	
 
def curvesDir():
 
    return path.join(root(),"curves")
 
    return path.join(root(), "curves")
 

	
 

	
 
def subFile(subname):
 
    return path.join(root(),"subs",subname)
 
    return path.join(root(), "subs", subname)
 

	
 

	
 
def subsDir():
 
    return path.join(root(),'subs')
 
    return path.join(root(), 'subs')
light9/subclient.py
Show inline comments
 
@@ -5,10 +5,12 @@ import time
 
import logging
 
log = logging.getLogger()
 

	
 

	
 
class SubClient:
 

	
 
    def __init__(self):
 
        """assumed that your init saves self.graph"""
 
        pass # we may later need init code for network setup
 
        pass  # we may later need init code for network setup
 

	
 
    def get_levels_as_sub(self):
 
        """Subclasses must implement this method and return a Submaster
 
@@ -19,17 +21,19 @@ class SubClient:
 

	
 
    def send_levels_loop(self, delay=1000):
 
        now = time.time()
 

	
 
        def done(sec):
 
            reactor.callLater(max(0, time.time() - (now + delay)),
 
            reactor.callLater(max(0,
 
                                  time.time() - (now + delay)),
 
                              self.send_levels_loop)
 

	
 
        def err(e):
 
            log.warn('subclient loop: %r', e)
 
            reactor.callLater(2, self.send_levels_loop)
 
            
 

	
 
        d = self._send_sub()
 
        d.addCallbacks(done, err)
 

	
 

	
 
    def _send_sub(self):
 
        try:
 
            with self.graph.currentState() as g:
light9/tkdnd.py
Show inline comments
 
from glob import glob
 
from os.path import join, basename
 

	
 

	
 
class TkdndEvent(object):
 
    """
 
    see http://www.ellogon.org/petasis/tcltk-projects/tkdnd/tkdnd-man-page
 
@@ -14,15 +15,15 @@ class TkdndEvent(object):
 
    unnecessarily change their types later.
 
    """
 
    substitutions = {
 
        "%A" : "action",
 
        "%b" : "button",
 
        "%D" : "data",
 
        "%m" : "modifiers",
 
        "%T" : "type",
 
        "%W" : "targetWindow",
 
        "%X" : "mouseX",
 
        "%Y" : "mouseY",
 
        }
 
        "%A": "action",
 
        "%b": "button",
 
        "%D": "data",
 
        "%m": "modifiers",
 
        "%T": "type",
 
        "%W": "targetWindow",
 
        "%X": "mouseX",
 
        "%Y": "mouseY",
 
    }
 

	
 
    @classmethod
 
    def makeEvent(cls, *args):
 
@@ -39,7 +40,9 @@ class TkdndEvent(object):
 
    def __repr__(self):
 
        return "<TkdndEvent %r>" % self.__dict__
 

	
 

	
 
class Hover(object):
 

	
 
    def __init__(self, widget, style):
 
        self.widget, self.style = widget, style
 
        self.oldStyle = {}
 
@@ -53,21 +56,22 @@ class Hover(object):
 
    def restore(self, ev):
 
        self.widget.configure(**self.oldStyle)
 

	
 

	
 
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')
 
    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=''):
 

	
 
def dragSourceRegister(widget, action='copy', datatype='text/uri-list',
 
                       data=''):
 
    """
 
    if the 'data' param is callable, it will be called every time to
 
    look up the current data.
 
@@ -87,19 +91,23 @@ def dragSourceRegister(widget,
 
            return
 
        return (action, datatype, dataValue)
 

	
 
    funcId = widget._register(init,
 
                              widget._substitute,
 
                              1 # needscleanup
 
                              )
 
    funcId = widget._register(
 
        init,
 
        widget._substitute,
 
        1  # needscleanup
 
    )
 
    widget.bind("<<DragInitCmd>>", funcId)
 

	
 
def dropTargetRegister(widget, typeList=None,
 
                       onDropEnter=None,
 
                       onDropPosition=None,
 
                       onDropLeave=None,
 
                       onDrop=None,
 
                       hoverStyle=None,
 
                       ):
 

	
 
def dropTargetRegister(
 
        widget,
 
        typeList=None,
 
        onDropEnter=None,
 
        onDropPosition=None,
 
        onDropLeave=None,
 
        onDrop=None,
 
        hoverStyle=None,
 
):
 
    """
 
    the optional callbacks will be called with a TkdndEvent
 
    argument.
 
@@ -116,11 +124,14 @@ def dropTargetRegister(widget, typeList=
 

	
 
    if hoverStyle is not None:
 
        hover = Hover(widget, hoverStyle)
 

	
 
        def wrappedDrop(ev):
 
            hover.restore(ev)
 
            if onDrop:
 
                return onDrop(ev)
 
        return dropTargetRegister(widget, typeList=typeList,
 

	
 
        return dropTargetRegister(widget,
 
                                  typeList=typeList,
 
                                  onDropEnter=hover.set,
 
                                  onDropLeave=hover.restore,
 
                                  onDropPosition=onDropPosition,
 
@@ -128,17 +139,17 @@ def dropTargetRegister(widget, typeList=
 

	
 
    if typeList is None:
 
        typeList = ['*']
 
    widget.tk.call(*(['tkdnd::drop_target', 'register', widget._w]+typeList))
 
    widget.tk.call(*(['tkdnd::drop_target', 'register', widget._w] + typeList))
 

	
 
    for sequence, handler in [
 
        ('<<DropEnter>>', onDropEnter),
 
        ('<<DropPosition>>', onDropPosition),
 
        ('<<DropLeave>>', onDropLeave),
 
        ('<<Drop>>', onDrop),
 
        ]:
 
    ]:
 
        if not handler:
 
            continue
 
        func = widget._register(handler, subst=TkdndEvent.makeEvent, needcleanup=1)
 
        func = widget._register(handler,
 
                                subst=TkdndEvent.makeEvent,
 
                                needcleanup=1)
 
        widget.bind(sequence, func + " " + TkdndEvent.tclSubstitutions)
 

	
 

	
light9/uihelpers.py
Show inline comments
 
"""all the tiny tk helper functions"""
 

	
 

	
 
#from Tkinter import Button
 
import logging, time
 
from rdflib import Literal
 
@@ -11,32 +10,34 @@ from light9.namespaces import L9
 
log = logging.getLogger("toplevel")
 

	
 
windowlocations = {
 
    'sub' : '425x738+00+00',
 
    'console' : '168x24+848+000',
 
    'leveldisplay' : '144x340+870+400',
 
    'cuefader' : '314x212+546+741',
 
    'effect' : '24x24+0963+338',
 
    'stage' : '823x683+37+030',
 
    'scenes' : '504x198+462+12',
 
    'sub': '425x738+00+00',
 
    'console': '168x24+848+000',
 
    'leveldisplay': '144x340+870+400',
 
    'cuefader': '314x212+546+741',
 
    'effect': '24x24+0963+338',
 
    'stage': '823x683+37+030',
 
    'scenes': '504x198+462+12',
 
}
 

	
 
def bindkeys(root,key, func):
 

	
 
def bindkeys(root, key, func):
 
    root.bind(key, func)
 
    for w in root.winfo_children():
 
        w.bind(key, func)
 

	
 

	
 
def toplevel_savegeometry(tl,name):
 
def toplevel_savegeometry(tl, name):
 
    try:
 
        geo = tl.geometry()
 
        if not geo.startswith("1x1"):
 
            f=open(".light9-window-geometry-%s" % name.replace(' ','_'),'w')
 
            f = open(".light9-window-geometry-%s" % name.replace(' ', '_'), 'w')
 
            f.write(tl.geometry())
 
        # else the window never got mapped
 
    except Exception as e:
 
        # it's ok if there's no saved geometry
 
        pass
 

	
 

	
 
def toplevelat(name, existingtoplevel=None, graph=None, session=None):
 
    tl = existingtoplevel or Toplevel()
 
    tl.title(name)
 
@@ -44,6 +45,7 @@ def toplevelat(name, existingtoplevel=No
 
    lastSaved = [None]
 
    setOnce = [False]
 
    graphSetTime = [0]
 

	
 
    def setPosFromGraphOnce():
 
        """
 
        the graph is probably initially empty, but as soon as it gives
 
@@ -83,11 +85,12 @@ def toplevelat(name, existingtoplevel=No
 
        tl.geometry(positionOnCurrentDesktop(windowlocations[name]))
 

	
 
    if graph is not None:
 
        tl._toplevelat_funcid = tl.bind("<Configure>",
 
                                        lambda ev,tl=tl,name=name: savePos(ev))
 
        tl._toplevelat_funcid = tl.bind(
 
            "<Configure>", lambda ev, tl=tl, name=name: savePos(ev))
 

	
 
    return tl
 

	
 

	
 
def positionOnCurrentDesktop(xform, screenWidth=1920, screenHeight=1440):
 
    size, x, y = xform.split('+')
 
    x = int(x) % screenWidth
 
@@ -101,105 +104,122 @@ def toggle_slider(s):
 
    else:
 
        s.set(0)
 

	
 

	
 
# for lambda callbacks
 
def printout(t):
 
    print('printout', t)
 

	
 

	
 
def printevent(ev):
 
    for k in dir(ev):
 
        if not k.startswith('__'):
 
            print('ev', k, getattr(ev,k))
 
            print('ev', k, getattr(ev, k))
 

	
 
def eventtoparent(ev,sequence):
 

	
 
def eventtoparent(ev, sequence):
 
    "passes an event to the parent, screws up TixComboBoxes"
 

	
 
    wid_class = str(ev.widget.__class__)
 
    if wid_class == 'Tix.ComboBox' or wid_class == 'Tix.TixSubWidget':
 
        return
 

	
 
    evdict={}
 
    evdict = {}
 
    for x in ['state', 'time', 'y', 'x', 'serial']:
 
        evdict[x]=getattr(ev,x)
 
        evdict[x] = getattr(ev, x)
 

	
 

	
 
#    evdict['button']=ev.num
 
    par=ev.widget.winfo_parent()
 
    if par!=".":
 
        ev.widget.nametowidget(par).event_generate(sequence,**evdict)
 
    par = ev.widget.winfo_parent()
 
    if par != ".":
 
        ev.widget.nametowidget(par).event_generate(sequence, **evdict)
 
    #else the event made it all the way to the top, unhandled
 

	
 

	
 
def colorlabel(label):
 
    """color a label based on its own text"""
 
    txt=label['text'] or "0"
 
    lev=float(txt)/100
 
    low=(80,80,180)
 
    high=(255,55,0o50)
 
    out = [int(l+lev*(h-l)) for h,l in zip(high,low)]
 
    col="#%02X%02X%02X" % tuple(out)
 
    txt = label['text'] or "0"
 
    lev = float(txt) / 100
 
    low = (80, 80, 180)
 
    high = (255, 55, 0o50)
 
    out = [int(l + lev * (h - l)) for h, l in zip(high, low)]
 
    col = "#%02X%02X%02X" % tuple(out)
 
    label.config(bg=col)
 

	
 

	
 
# TODO: get everyone to use this
 
def colorfade(low, high, percent):
 
    '''not foolproof.  make sure 0 < percent < 1'''
 
    out = [int(l+percent*(h-l)) for h,l in zip(high,low)]
 
    col="#%02X%02X%02X" % tuple(out)
 
    out = [int(l + percent * (h - l)) for h, l in zip(high, low)]
 
    col = "#%02X%02X%02X" % tuple(out)
 
    return col
 

	
 

	
 
def colortotuple(anytkobj, colorname):
 
    'pass any tk object and a color name, like "yellow"'
 
    rgb = anytkobj.winfo_rgb(colorname)
 
    return [v / 256 for v in rgb]
 

	
 

	
 
class Togglebutton(Button):
 
    """works like a single radiobutton, but it's a button so the
 
    label's on the button face, not to the side. the optional command
 
    callback is called on button set, not on unset. takes a variable
 
    just like a checkbutton"""
 
    def __init__(self,parent,variable=None,command=None,downcolor='red',**kw):
 

	
 
    def __init__(self,
 
                 parent,
 
                 variable=None,
 
                 command=None,
 
                 downcolor='red',
 
                 **kw):
 

	
 
        self.oldcommand = command
 
        Button.__init__(self,parent,command=self.invoke,**kw)
 
        Button.__init__(self, parent, command=self.invoke, **kw)
 

	
 
        self._origbkg = self.cget('bg')
 
        self.downcolor = downcolor
 

	
 
        self._variable = variable
 
        if self._variable:
 
            self._variable.trace('w',self._varchanged)
 
            self._variable.trace('w', self._varchanged)
 
            self._setstate(self._variable.get())
 
        else:
 
            self._setstate(0)
 

	
 
        self.bind("<Return>",self.invoke)
 
        self.bind("<1>",self.invoke)
 
        self.bind("<space>",self.invoke)
 
        self.bind("<Return>", self.invoke)
 
        self.bind("<1>", self.invoke)
 
        self.bind("<space>", self.invoke)
 

	
 
    def _varchanged(self,*args):
 
    def _varchanged(self, *args):
 
        self._setstate(self._variable.get())
 

	
 
    def invoke(self,*ev):
 
    def invoke(self, *ev):
 
        if self._variable:
 
            self._variable.set(not self.state)
 
        else:
 
            self._setstate(not self.state)
 

	
 
        if self.oldcommand and self.state: # call command only when state goes to 1
 
        if self.oldcommand and self.state:  # call command only when state goes to 1
 
            self.oldcommand()
 
        return "break"
 

	
 
    def _setstate(self,newstate):
 
    def _setstate(self, newstate):
 
        self.state = newstate
 
        if newstate: # set
 
            self.config(bg=self.downcolor,relief='sunken')
 
        else: # unset
 
            self.config(bg=self._origbkg,relief='raised')
 
        if newstate:  # set
 
            self.config(bg=self.downcolor, relief='sunken')
 
        else:  # unset
 
            self.config(bg=self._origbkg, relief='raised')
 
        return "break"
 

	
 

	
 
class FancyDoubleVar(DoubleVar):
 
    def __init__(self,master=None):
 
        DoubleVar.__init__(self,master)
 
        self.callbacklist = {} # cbname : mode
 
        self.namedtraces = {} # name : cbname
 
    def trace_variable(self,mode,callback):
 

	
 
    def __init__(self, master=None):
 
        DoubleVar.__init__(self, master)
 
        self.callbacklist = {}  # cbname : mode
 
        self.namedtraces = {}  # name : cbname
 

	
 
    def trace_variable(self, mode, callback):
 
        """Define a trace callback for the variable.
 

	
 
        MODE is one of "r", "w", "u" for read, write, undefine.
 
@@ -213,27 +233,32 @@ class FancyDoubleVar(DoubleVar):
 

	
 
        # we build a list of the trace callbacks (the py functrions and the tcl functionnames)
 
        self.callbacklist[cbname] = mode
 
#        print "added trace:",callback,cbname
 
        #        print "added trace:",callback,cbname
 

	
 
        return cbname
 
    trace=trace_variable
 

	
 
    trace = trace_variable
 

	
 
    def disable_traces(self):
 
        for cb,mode in list(self.callbacklist.items()):
 
#            DoubleVar.trace_vdelete(self,v[0],k)
 
            self._tk.call("trace", "vdelete", self._name, mode,cb)
 
        for cb, mode in list(self.callbacklist.items()):
 
            #            DoubleVar.trace_vdelete(self,v[0],k)
 
            self._tk.call("trace", "vdelete", self._name, mode, cb)
 
            # but no master delete!
 

	
 
    def recreate_traces(self):
 
        for cb,mode in list(self.callbacklist.items()):
 
#            self.trace_variable(v[0],v[1])
 
            self._tk.call("trace", "variable", self._name, mode,cb)
 
        for cb, mode in list(self.callbacklist.items()):
 
            #            self.trace_variable(v[0],v[1])
 
            self._tk.call("trace", "variable", self._name, mode, cb)
 

	
 
    def trace_named(self, name, callback):
 
        if name in self.namedtraces:
 
            print("FancyDoubleVar: already had a trace named %s - replacing it" % name)
 
            print(
 
                "FancyDoubleVar: already had a trace named %s - replacing it" %
 
                name)
 
            self.delete_named(name)
 

	
 
        cbname = self.trace_variable('w',callback) # this will register in self.callbacklist too
 
        cbname = self.trace_variable(
 
            'w', callback)  # this will register in self.callbacklist too
 

	
 
        self.namedtraces[name] = cbname
 
        return cbname
 
@@ -243,24 +268,30 @@ class FancyDoubleVar(DoubleVar):
 

	
 
            cbname = self.namedtraces[name]
 

	
 
            self.trace_vdelete('w',cbname)
 
	    #self._tk.call("trace","vdelete",self._name,'w',cbname)
 
            self.trace_vdelete('w', cbname)
 
            #self._tk.call("trace","vdelete",self._name,'w',cbname)
 
            print("FancyDoubleVar: successfully deleted trace named %s" % name)
 
        else:
 
            print("FancyDoubleVar: attempted to delete named %s which wasn't set to any function" % name)
 
            print(
 
                "FancyDoubleVar: attempted to delete named %s which wasn't set to any function"
 
                % name)
 

	
 

	
 
def get_selection(listbox):
 
    'Given a listbox, returns first selection as integer'
 
    selection = int(listbox.curselection()[0]) # blech
 
    selection = int(listbox.curselection()[0])  # blech
 
    return selection
 

	
 
if __name__=='__main__':
 
    root=Tk()
 

	
 
if __name__ == '__main__':
 
    root = Tk()
 
    root.tk_focusFollowsMouse()
 
    iv=IntVar()
 
    iv = IntVar()
 

	
 
    def cb():
 
        print("cb!")
 
    t = Togglebutton(root,text="testbutton",command=cb,variable=iv)
 

	
 
    t = Togglebutton(root, text="testbutton", command=cb, variable=iv)
 
    t.pack()
 
    Entry(root,textvariable=iv).pack()
 
    Entry(root, textvariable=iv).pack()
 
    root.mainloop()
light9/updatefreq.py
Show inline comments
 
"""calculates your updates-per-second"""
 

	
 
import time
 

	
 
import time
 

	
 
class Updatefreq:
 
    """make one of these, call update() on it as much as you want,
 
@@ -9,26 +9,25 @@ class Updatefreq:
 

	
 
    the samples param to __init__ specifies how many past updates will
 
    be stored.  """
 
    
 
    def __init__(self,samples=20):
 
        self.times=[0]
 
        self.samples=samples
 

	
 
    def __init__(self, samples=20):
 
        self.times = [0]
 
        self.samples = samples
 

	
 
    def update(self):
 

	
 
        """call this every time you do an update"""
 
        self.times=self.times[-self.samples:]
 
        self.times = self.times[-self.samples:]
 
        self.times.append(time.time())
 

	
 
    def __float__(self):
 
        
 
        """a cheap algorithm, for now, which looks at the first and
 
        last times only"""
 

	
 
        try:
 
            hz=len(self.times)/(self.times[-1]-self.times[0])
 
            hz = len(self.times) / (self.times[-1] - self.times[0])
 
        except ZeroDivisionError:
 
            return 0.0
 
        return hz
 

	
 
    def __str__(self):
 
        return "%.2fHz"%float(self)
 
        return "%.2fHz" % float(self)
light9/wavelength.py
Show inline comments
 
#!/usr/bin/python
 

	
 
import sys, wave
 

	
 
import sys, wave
 

	
 
def wavelength(filename):
 
    filename = filename.replace('.ogg', '.wav')
 
    wavefile = wave.open(filename, 'rb')
 

	
 
    framerate = wavefile.getframerate() # frames / second
 
    nframes = wavefile.getnframes() # number of frames
 
    framerate = wavefile.getframerate()  # frames / second
 
    nframes = wavefile.getnframes()  # number of frames
 
    song_length = nframes / framerate
 

	
 
    return song_length
 

	
 

	
 
if __name__ == "__main__":
 
    for songfile in sys.argv[1:]:
 
        print(songfile, wavelength(songfile))
light9/wavepoints.py
Show inline comments
 
import wave, audioop
 

	
 
import wave, audioop
 

	
 
def simp(filename, seconds_per_average=0.001):
 
    """smaller seconds_per_average means fewer data points"""
 
    wavefile = wave.open(filename, 'rb')
 
    print("# gnuplot data for %s, seconds_per_average=%s" % \
 
        (filename, seconds_per_average))
 
    print("# %d channels, samplewidth: %d, framerate: %s, frames: %d\n# Compression type: %s (%s)" % wavefile.getparams())
 
    print(
 
        "# %d channels, samplewidth: %d, framerate: %s, frames: %d\n# Compression type: %s (%s)"
 
        % wavefile.getparams())
 

	
 
    framerate = wavefile.getframerate() # frames / second
 
    framerate = wavefile.getframerate()  # frames / second
 
    frames_to_read = int(framerate * seconds_per_average)
 
    print("# frames_to_read=%s" % frames_to_read)
 

	
 
@@ -29,12 +31,12 @@ def simp(filename, seconds_per_average=0
 
        values.append(m)
 
        count += frames_to_read
 
        # if count>1000000:
 
            # break
 
        # break
 

	
 
    # find the min and max
 
    min_value, max_value = min(values), max(values)
 
    points = [] # (secs,height)
 
    points = []  # (secs,height)
 
    for count, value in time_and_max:
 
        points.append((count/framerate,
 
                       (value - min_value) / (max_value - min_value)))
 
        points.append(
 
            (count / framerate, (value - min_value) / (max_value - min_value)))
 
    return points
0 comments (0 inline, 0 general)