summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xinterface/chaserview.py15
-rwxr-xr-xinterface/input/parsers.py25
-rw-r--r--interface/interface.py109
3 files changed, 120 insertions, 29 deletions
diff --git a/interface/chaserview.py b/interface/chaserview.py
index 7a6a8db..2c94240 100755
--- a/interface/chaserview.py
+++ b/interface/chaserview.py
@@ -4,7 +4,7 @@ import curses
import math
import threading
-from blc2.constants import INFTY, MANUAL
+from blc2.constants import INFTY, MANUAL, JOIN, CHASERSTEP
CURSES_LOCK = threading.RLock()
@@ -80,7 +80,7 @@ class ChaserView:
c = self._chaser
w = self._width - 2
- self.win.addstr(1, 1, self.fit(("%d: "% c.id) + c.name, w, True), curses.A_REVERSE if self._highlight else 0)
+ self.win.addstr(1, 1, self.fit(("%d: "% c.id) + c.name + " (%s)" % ("Join" if c.type == JOIN else c.advance_mode), w, True), curses.A_REVERSE if self._highlight else 0)
maxsteps = self._height - 4
if maxsteps < len(c.steps):
@@ -97,19 +97,22 @@ class ChaserView:
last = len(c.steps)
steps = c.steps[first:last]
for n, s in enumerate(steps, 1):
- if s.index == self._selected:
+ if first+n-1 == self._selected:
attrs = curses.A_REVERSE
else:
attrs = 0
- if s.function is not None:
+ if s.type == CHASERSTEP and s.function is not None:
ft = s.function.type[0].upper()
fid = str(s.function.id)
+ elif s.type != CHASERSTEP:
+ ft = s.type[0].upper()
+ fid = str(s.id)
else:
ft = "-"
fid = "---"
- t = "%s%3s%s|%s:%s:%s" % (ft, fid, '*' if s.duration_mode == MANUAL else ' ', format_time(s.fade_in), format_time(s.duration), format_time(s.fade_out))
- self.win.addstr(n+2, 1, self.fit((self._numformat % (s.index+1)) + ": " + s.name, w-len(t), pad=True)+t, attrs)
+ t = "%s%3s%s|%s:%s:%s" % (ft, fid, '*' if (s.type == CHASERSTEP and s.duration_mode == MANUAL) else ' ', format_time(s.fade_in), format_time(s.duration), format_time(s.fade_out))
+ self.win.addstr(n+2, 1, self.fit((self._numformat % (first+n)) + ": " + s.name, w-len(t), pad=True)+t, attrs)
if first > 0:
self.win.addch(3, self._width//2, '⯅')
diff --git a/interface/input/parsers.py b/interface/input/parsers.py
index 7dc7d82..64ba7c4 100755
--- a/interface/input/parsers.py
+++ b/interface/input/parsers.py
@@ -101,6 +101,30 @@ def parse_num(s):
return (None if not buff else int(buff)), s, buff
+def parse_numlist(s):
+ if not s:
+ return None, s, None
+
+ rs = []
+ disp = []
+ tc = False
+ while s:
+ r, s, d = parse_num(s)
+ if r is None:
+ break
+ tc = False
+ rs.append(r)
+ disp.append(d)
+ if s and s[0] == ',':
+ s = s[1:]
+ tc = True
+ else:
+ break
+
+ if not rs:
+ return None, s, None
+ return tuple(rs), s, ", ".join(disp) + (", " if tc else "")
+
_POSTFIXES = "mcisahkegtp"
def parse_time(s):
@@ -201,4 +225,5 @@ PARSE_MAP = {
"$quoted_string": parse_quotedstring,
"$letter": parse_any_letter,
"$time": parse_time,
+ "$numlist": parse_numlist,
}
diff --git a/interface/interface.py b/interface/interface.py
index 48f3d24..500728c 100644
--- a/interface/interface.py
+++ b/interface/interface.py
@@ -10,7 +10,8 @@ from blc2.functions.audio import Audio
from blc2.functions.scene import Scene
from blc2.functions.chaser import Chaser
from blc2.functions.chaserstep import ChaserStep
-from blc2.constants import SCENE, CHASER, AUDIO, MANUAL, INHERIT, INFTY
+from blc2.functions.join import Join
+from blc2.constants import SCENE, CHASER, AUDIO, MANUAL, INHERIT, INFTY, CHASERSTEP, JOIN, ONESHOT, LOOP
from blc2.topology import Fixture
@@ -31,7 +32,7 @@ def wrap_curses(f):
return curses.wrapper(lambda stdscr: f(*args, stdscr, **kwargs))
return inner
-__version__ = "v0.0.2"
+__version__ = "v0.0.3"
class Interface:
def _compute_sizes(self, height, width):
@@ -140,7 +141,7 @@ class Interface:
self.handle_show(f)
self.channel_bank.highlight = True
self.input.context = self.context_scene
- elif f.type == CHASER:
+ elif f.type in (CHASER, JOIN):
self.chaser = f
cv = [c for c in self.chaser_views if c.chaser == f]
if not cv:
@@ -153,7 +154,10 @@ class Interface:
cv = cv[0]
self.current_cv = cv
self.current_cv.highlight = True
- self.input.context = self.context_chaser
+ if f.type == CHASER:
+ self.input.context = self.context_chaser
+ elif f.type == JOIN:
+ self.input.context = self.context_join
elif f.type == AUDIO:
self.primitive = f
self.handle_show(f)
@@ -168,7 +172,7 @@ class Interface:
if fid not in self.w.functions:
return "No such function"
f = self.w.functions[fid]
- if f.type != CHASER:
+ if f.type not in (CHASER, JOIN):
return "Can only add chasers!"
with CURSES_LOCK:
if True in (c.chaser.id for c in self.chaser_views):
@@ -343,7 +347,10 @@ class Interface:
self.current_cv.highlight = True
self.current_cv.selected = sel
- self.input.context = self.context_chaser
+ if c.type == CHASER:
+ self.input.context = self.context_chaser
+ else:
+ self.input.context = self.context_join
self.chaser = c
else:
if isinstance(self.channel_bank, AudioView):
@@ -423,8 +430,8 @@ class Interface:
self.current_cv.selected = num - 1
s = self.current_cv.chaser.steps[num-1]
- if s.function is not None and s.function.type in (SCENE, AUDIO,):
- self.handle_show(s.function)
+ if (s.type == CHASERSTEP and s.function is not None and s.function.type in (SCENE, AUDIO,)) or s.type in (SCENE, AUDIO,):
+ self.handle_show(s.function if s.type == CHASERSTEP else s)
def chaser_edit(self, num=None):
with self.w_lock:
@@ -436,10 +443,10 @@ class Interface:
return "No step selected"
c = self.current_cv.chaser.steps[self.current_cv.selected]
- if c.function is None:
+ if c.type == CHASERSTEP and c.function is None:
return "No function on step"
-
- self.handle_enter(c.function.id)
+
+ self.handle_enter(c.function.id if c.type == CHASERSTEP else c.id)
def chaser_delete(self, num=None):
with self.w_lock:
@@ -452,15 +459,22 @@ class Interface:
c = self.current_cv.chaser
s = c.steps[self.current_cv.selected]
+ sel = self.current_cv.selected
with CURSES_LOCK:
- if askyesnocancel(self.stdscr, "Really delete step %d?" % (s.index+1), resize=self._resize):
- sel = s.index
- s.delete()
- if not c.steps:
- sel = None
+ if c.type == CHASER:
+ if askyesnocancel(self.stdscr, "Really delete step %d?" % (s.index+1), resize=self._resize):
+ sel = s.index
+ s.delete()
else:
- sel = max(0, sel-1)
- self.current_cv.set_chaser(c, sel)
+ return
+ else:
+ c.delete_step(s)
+
+ if not c.steps:
+ sel = None
+ else:
+ sel = max(0, sel-1)
+ self.current_cv.set_chaser(c, sel)
self._resize()
def chaser_fade(self, t, out=False):
@@ -501,19 +515,30 @@ class Interface:
if fid not in self.w.functions:
return "No such function"
f = self.w.functions[fid]
- if f.type not in (SCENE, AUDIO, CHASER):
+ if f.type not in (SCENE, AUDIO, CHASER, JOIN):
return "Invalid function"
else:
f = None
c = self.current_cv.chaser
- s = ChaserStep(c, index=index, name=name, function=f)
- self.current_cv.set_chaser(c, s.index)
+ if c.type == CHASER:
+ if name is None and f is not None:
+ name = "Step \"%s\"" % f.name
+ s = ChaserStep(c, index=index, name=name, function=f)
+ self.current_cv.set_chaser(c, s.index)
+ else:
+ if f.id in (i.id for i in c.steps):
+ return "Already added"
+ c.add_step(f)
+ self.current_cv.set_chaser(c, len(c.steps)-1)
#self.chaser_edit(s.index+1)
def chaser_new_new(self, index, name, fname, type_):
with self.w_lock:
+ if name is None and f is not None:
+ name = "Step \"%s\"" % f.name
+
f = type_(self.w, name=fname)
return self.chaser_new(index, name, fid=f.id)
@@ -603,7 +628,7 @@ class Interface:
self.channel_bank.set_values(values)
self.channel_bank.title = "LIVE: %7.2fs" % t
- for d, cv in zip(self.renderer._data, self.chaser_views):
+ for d, cv in zip(self.renderer._data, (i for i in self.chaser_views if i.chaser.type == CHASER)):
cv.selected = d.steps[-1].index if d.steps else None
self.input.win.move(*syx)
@@ -617,7 +642,7 @@ class Interface:
self.channel_bank.highlight = True
self.rendering = True
- self.renderer.set_functions(*((cv.chaser, cv.chaser.get_data(cv.selected)) for cv in self.chaser_views))
+ self.renderer.set_functions(*((cv.chaser, cv.chaser.get_data(cv.selected)) for cv in self.chaser_views if cv.chaser.type == CHASER))
self.renderer.start()
self.input.context = self.context_run
@@ -695,6 +720,11 @@ class Interface:
"- Fade out: %7.3f" % (f.fade_out/1000),
))
+ def chaser_mode(self, mode):
+ with self.w_lock:
+ self.current_cv.chaser.advance_mode = mode
+ self.current_cv.set_chaser(self.current_cv.chaser, self.current_cv.selected)
+
def __init__(self, path, output):
## Have to do most of the actual initialization in the main method, as curses isn't
## ready yet.
@@ -728,6 +758,7 @@ class Interface:
("new scene $quoted_string", lambda n: self.base_new(n, Scene)),
("new chaser $quoted_string", lambda n: self.base_new(n, Chaser)),
("new audio $quoted_string", lambda n: self.base_new(n, Audio)),
+ ("new join $quoted_string", lambda n: self.base_new(n, Join)),
("add $num", self.base_add),
("subtract $letter", lambda n: self.base_remove(n, True)),
@@ -742,6 +773,7 @@ class Interface:
("list scenes", lambda: self.list_functions(SCENE)),
("list chasers", lambda: self.list_functions(CHASER)),
("list audio", lambda: self.list_functions(AUDIO)),
+ ("list joins", lambda: self.list_functions(JOIN)),
("currentstatus", self.current_status),
@@ -792,6 +824,8 @@ class Interface:
("move $num", self.chaser_move),
("set fade in $time", self.chaser_fade),
("set fade out $time", lambda t: self.chaser_fade(t, True)),
+ ("set mode oneshot", lambda: self.chaser_mode(ONESHOT)),
+ ("set mode loop", lambda: self.chaser_mode(LOOP)),
("set length $time", self.chaser_duration),
("unbind", self.chaser_unset),
("bind $num", self.chaser_bind),
@@ -800,6 +834,7 @@ class Interface:
("list scenes", lambda: self.list_functions(SCENE)),
("list chasers", lambda: self.list_functions(CHASER)),
("list audio", lambda: self.list_functions(AUDIO)),
+ ("list joins", lambda: self.list_functions(JOIN)),
("info", lambda: self.chaser_info(None)),
("info $num", self.chaser_info),
@@ -838,6 +873,7 @@ class Interface:
("list scenes", lambda: self.list_functions(SCENE)),
("list chasers", lambda: self.list_functions(CHASER)),
("list audio", lambda: self.list_functions(AUDIO)),
+ ("list joins", lambda: self.list_functions(JOIN)),
("rename $quoted_string", self.primitive_rename),
@@ -902,6 +938,33 @@ class Interface:
"currentstatus" : "Display information about the system's current status."
}, self.help)
+ self.context_join = Input.parse_context((
+ ("choose $num", self.chaser_select),
+
+ ("edit", self.chaser_edit),
+ ("edit $num", self.chaser_edit),
+
+ ("delete", self.chaser_delete),
+ ("delete $num", self.chaser_delete),
+
+ ("add", lambda: self.chaser_new(-1, "")),
+ ("add from $num", lambda s: self.chaser_new(-1, "", s)),
+ ("add from new scene $quoted_string", lambda s: self.chaser_new_new(-1, "", s, Scene)),
+ ("add from new audio $quoted_string", lambda s: self.chaser_new_new(-1, "", s, Audio)),
+
+ ("rename $quoted_string", self.chaser_rename_self),
+
+ ("list fixtures", self.list_fixtures),
+ ("list scenes", lambda: self.list_functions(SCENE)),
+ ("list chasers", lambda: self.list_functions(CHASER)),
+ ("list audio", lambda: self.list_functions(AUDIO)),
+ ("list joins", lambda: self.list_functions(JOIN)),
+
+ ("pager page", self.page),
+ ("pager clear", self.page_clear),
+ ("quit", self.handle_exit),
+ ))
+
self.output = output
self.renderer = Renderer(self.w, self.w_lock, self.output, self._render_callback)
self.rendering = False