Files
@ c5a79314afdf
Branch filter:
Location: light9/light9/Submaster.py
c5a79314afdf
5.9 KiB
text/x-python
bigger asco window
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 | from __future__ import division
import os
from light9.TLUtility import dict_scale, dict_max
from light9 import Patch, showconfig
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()
def reload(self):
if self.temporary:
return
try:
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])
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 all_zeros(self):
return 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):
levels = ' '.join(["%s:%.2f" % item for item in self.levels.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)
for k in all_keys:
xfaded_sub.set_level(k,
linear_fade(self.levels.get(k, 0),
otherlevels.get(k, 0),
amount))
return xfaded_sub
def linear_fade(start, end, amount):
"""Fades between two floats by an amount. amount is a float between
0 and 1. If amount is 0, it will return the start value. If it is 1,
the end value will be returned."""
level = start + (amount * (end - start))
return level
def sub_maxes(*subs):
nonzero_subs = [s for s in subs if not s.all_zeros()]
name = "max(%s)" % ", ".join([repr(s) for s in nonzero_subs])
return Submaster(name,
dict_max(*[sub.levels for sub in nonzero_subs]),
temporary=1)
class Submasters:
"Collection o' Submaster objects"
def __init__(self):
self.submasters = {}
files = os.listdir(showconfig.subsDir())
for filename in files:
# we don't want these files
if filename.startswith('.') or filename.endswith('~') or \
filename.startswith('CVS'):
continue
self.submasters[filename] = Submaster(filename)
def get_all_subs(self):
"All Submaster objects"
l = self.submasters.items()
l.sort()
l = [x[1] for x in l]
songs = []
notsongs = []
for s in l:
if s.name.startswith('song'):
songs.append(s)
else:
notsongs.append(s)
combined = notsongs + songs
return combined
def get_sub_by_name(self, name):
"Makes a new sub if there isn't one."
return self.submasters.get(name, Submaster(name))
__getitem__ = get_sub_by_name
if __name__ == "__main__":
Patch.reload_data()
s = Submasters()
print s.get_all_subs()
if 0: # turn this on to normalize all subs
for sub in s.get_all_subs():
print "before", sub
sub.normalize_patch_names()
sub.save()
print "after", sub
|