Changeset - f8b5cb5fbeed
[Not reviewed]
default
0 2 0
dmcc - 21 years ago 2003-07-09 03:59:40

- CueFader is hopefully done:
- CueFader is hopefully done:
- The TimedGoButton accepts a wheel to change the times. You can also
enter times directly.
- TimedGoButton really has a default starting time of 2 now. (there was
a variable attached to the wrong widget before)
- We send DMX levels with dmxclient now.
- Autoload Times is a new option.
- We load times from the next cue if Autoload Times is true.
- Time predictions in the LabelledScale are slightly better. You still
can change the time of an active fade.
- Cue cache and DMX level computing now have their own functions, which
get called at (hopefully) All The Right Times.
- There are even some docs now!
- Cues: sub_level parsing is better, will only throw out one line if
it encounters problems (instead of the rest of the cue)
- CueList: lots of 0 vs. None bugs fixed.
- TkCueList: stores a reference to the controlling fader so it can alert
it about changed cues.
- CueEditron: You can edit sub_levels now.
- cuelist1 was edited, checking it in for consistency's sake
2 files changed with 165 insertions and 80 deletions:
0 comments (0 inline, 0 general)
flax/CueFaders.py
Show inline comments
 
@@ -3,7 +3,7 @@ import Tix as Tk
 
import time
 
from TreeDict import TreeDict, allow_class_to_be_pickled
 
from TLUtility import enumerate
 
import Submaster
 
import Submaster, dmxclient
 

	
 
cue_state_indicator_colors = {
 
             # bg       fg
 
@@ -75,19 +75,30 @@ class TimedGoButton(Tk.Frame):
 
        self.button.pack(fill='both', expand=1, side='left')
 

	
 
        self.timer_var = Tk.DoubleVar()
 
        self.timer_entry = Tk.Control(self, step=0.5, min=0, integer=0)
 
        self.timer_entry.entry.configure(textvariable=self.timer_var, width=5, 
 
            bg='black', fg='white')
 
        self.timer_entry = Tk.Control(self, step=0.5, min=0, integer=0, 
 
            variable=self.timer_var, selectmode='immediate')
 
        for widget in (self.timer_entry, self.timer_entry.entry, 
 
            self.timer_entry.incr, self.timer_entry.decr, self.button, self):
 
            widget.bind("<4>", self.wheelscroll)
 
            widget.bind("<5>", self.wheelscroll)
 
        self.timer_entry.entry.configure(width=5, bg='black', fg='white')
 
        self.timer_entry.pack(fill='y', side='left')
 
        self.timer_var.set(2)
 
        self.disabled = (self.button['state'] == 'disabled')
 
        self.fading = 0
 
    def wheelscroll(self, event):
 
        """Mouse wheel increments or decrements timer."""
 
        if event.num == 4: # scroll up
 
            self.timer_entry.increment()
 
        else:            # scroll down
 
            self.timer_entry.decrement()
 
    def start_fade(self, end_level=1):
 
        try:
 
            fade_time = float(self.timer_var.get())
 
        except ValueError:
 
            # since we use a control now, i don't think we need to worry about
 
            # validation any more.
 
            print "can't fade -- bad time"
 
            print ">>> Can't fade -- bad time", self.timer_var.get()
 
            return
 

	
 
        self.start_time = time.time()
 
@@ -130,8 +141,11 @@ class CueFader(Tk.Frame):
 
    def __init__(self, master, cuelist):
 
        Tk.Frame.__init__(self, master, bg='black')
 
        self.cuelist = cuelist
 
        self.auto_shift = Tk.IntVar()
 
        self.auto_shift.set(1)
 
        self.cuelist.set_fader(self)
 

	
 
        self.last_levels_sent = 0
 
        self.current_dmx_levels = [0] * 68
 
        self.after(0, self.send_dmx_levels_loop) # start DMX sending loop
 

	
 
        # this is a mechanism to stop Tk from autoshifting too much.
 
        # if this variable is true, the mouse button is down.  we don't want
 
@@ -150,12 +164,24 @@ class CueFader(Tk.Frame):
 
            fg='white', bg='blue')
 
        self.set_prev_button.pack(side='left')
 

	
 
        self.auto_shift = Tk.IntVar()
 
        self.auto_shift.set(1)
 

	
 
        self.auto_shift_checkbutton = Tk.Checkbutton(topframe, 
 
            variable=self.auto_shift, text='Autoshift', 
 
            command=self.toggle_autoshift, bg='black', fg='white',
 
            highlightbackground='black')
 
        self.auto_shift_checkbutton.pack(fill='both', side='left')
 

	
 
        self.auto_load_times = Tk.IntVar()
 
        self.auto_load_times.set(1)
 

	
 
        self.auto_load_times_checkbutton = Tk.Checkbutton(topframe, 
 
            variable=self.auto_load_times, text='Autoload Times', 
 
            command=self.toggle_autoshift, bg='black', fg='white', 
 
            highlightbackground='black')
 
        self.auto_load_times_checkbutton.pack(fill='both', side='left')
 

	
 
        self.set_next_button = Tk.Button(topframe, text='Set Next',
 
            command=lambda: cuelist.set_selection_as_next(),
 
            fg='white', bg='red')
 
@@ -188,6 +214,8 @@ class CueFader(Tk.Frame):
 

	
 
            scale.scale_var.trace('w', \
 
                lambda x, y, z, name=name, scale=scale: self.xfade(name, scale))
 
            go.timer_var.trace('w',
 
                lambda x, y, z, scale=scale: scale.update_value_label())
 

	
 
            def button_press(event, name=name, scale=scale):
 
                self.no_shifts_until_release = 1 # prevent shifts until release
 
@@ -198,8 +226,48 @@ class CueFader(Tk.Frame):
 
            scale.scale.bind("<ButtonPress>", button_press)
 
            scale.scale.bind("<ButtonRelease>", button_release)
 
        faderframe.pack(side='bottom', fill='both', expand=1)
 

	
 
        self.current_dir = 'Next'
 
        self.cues_as_subs = {}
 
        self.update_cue_cache()
 
    def reload_cue_times(self):
 
        prev, cur, next = self.cuelist.get_current_cues()
 
        self.go_buttons['Next'].set_time(next.time)
 
    def update_cue_cache(self):
 
        """Rebuilds subs from the current cues.  As this is expensive, we don't
 
        do it unless necessary (i.e. whenever we shift or a cue is edited)"""
 
        # load the subs to fade between
 
        for cue, name in zip(self.cuelist.get_current_cues(), 
 
                             ('Prev', 'Cur', 'Next')):
 
            self.cues_as_subs[name] = cue.get_levels_as_sub()
 
        self.compute_dmx_levels()
 
    def compute_dmx_levels(self):
 
        """Compute the DMX levels to send.  This should get called whenever the
 
        DMX levels could change: either during a crossfade or when a cue is
 
        edited.  Since this is called when we know that a change might occur,
 
        we will send the new levels too."""
 
        cur_sub = self.cues_as_subs.get('Cur')
 
        if cur_sub:
 
            scale = self.scales[self.current_dir]
 
            scale_val = scale.scale_var.get() 
 

	
 
            other_sub = self.cues_as_subs[self.current_dir]
 
            current_levels_as_sub = cur_sub.crossfade(other_sub, scale_val)
 
            self.current_dmx_levels = current_levels_as_sub.get_dmx_list()
 
            self.send_dmx_levels()
 
    def send_dmx_levels(self):
 
        # print "send_dmx_levels", self.current_dmx_levels
 
        dmxclient.outputlevels(self.current_dmx_levels)
 
        self.last_levels_sent = time.time()
 
    def send_dmx_levels_loop(self):
 
        diff = time.time() - self.last_levels_sent
 
        if diff >= 2: # too long since last send
 
            self.send_dmx_levels()
 
            self.after(200, self.send_dmx_levels_loop)
 
        else:
 
            self.after(int((2 - diff) * 100), self.send_dmx_levels_loop)
 
    def get_scale_desc(self, val, name):
 
        """Returns a description to the TimedGoButton"""
 
        go_button = self.go_buttons.get(name)
 
        if go_button:
 
            time = go_button.get_time()
 
@@ -221,11 +289,9 @@ class CueFader(Tk.Frame):
 
            scale.scale.set(0)
 
        self.cuelist.shift((-1, 1)[name == 'Next'])
 

	
 
        # now load the subs to fade between
 
        for cue, name in zip(self.cuelist.get_current_cues(), 
 
                             ('Prev', 'Cur', 'Next')):
 
            self.cues_as_subs[name] = cue.get_levels_as_sub()
 
        print "cues_as_subs", self.cues_as_subs
 
        self.update_cue_cache()
 
        if self.auto_load_times.get():
 
            self.reload_cue_times()
 
    def autoshift(self, name, scale):
 
        scale_val = scale.scale_var.get() 
 

	
 
@@ -254,13 +320,8 @@ class CueFader(Tk.Frame):
 
            self.scales[d].enable()
 
            self.go_buttons[d].enable()
 

	
 
        cur_sub = self.cues_as_subs.get('Cur')
 
        if cur_sub:
 
            other_sub = self.cues_as_subs[name]
 
            # print 'fade between %s and %s (%.2f)' % (cur_sub, other_sub, scale_val)
 
            self.current_levels_as_sub = cur_sub.crossfade(other_sub, scale_val)
 
            print "current levels", self.current_levels_as_sub.get_dmx_list()
 
            # print
 
        self.current_dir = name
 
        self.compute_dmx_levels()
 
    def opposite_direction(self, d):
 
        if d == 'Next':
 
            return 'Prev'
 
@@ -282,19 +343,17 @@ class Cue:
 
        will reload the submasters from disk, combine all subs together, and
 
        then compute the normalized form."""
 
        subdict = {}
 
        for line in self.sub_levels.split(','):
 
        try:
 
            print self, self.sub_levels
 
            for line in self.sub_levels.split(','):
 
                line = line.strip()
 
                # print 'line', line
 
                if not line: 
 
                    continue
 
                sub, scale = line.split(':')
 
                # print 'sub', sub, 'scale', scale
 
                sub = sub.strip()
 
                scale = float(scale)
 
                subdict[sub] = scale
 
            # print 'subdict', subdict
 
        except (ValueError, AttributeError):
 
            print "parsing error when computing sub for", self
 
            except ValueError:
 
                print "Parsing error for '%s' in %s" % (self.sub_levels, self)
 

	
 
        s = Submaster.Submasters()
 
        newsub = Submaster.sub_maxes(*[s[sub] * scale 
 
@@ -347,23 +406,27 @@ class CueList:
 
    def set_prev(self, index):
 
        self.prev_pointer = index
 
    def bound_index(self, index):
 
        if not self.cues:
 
        if not self.cues or index < 0:
 
            return None
 
        else:
 
            return max(0, min(index, len(self.cues) - 1))
 
            return min(index, len(self.cues) - 1)
 
    def get_current_cue_indices(self):
 
        """Returns a list of the indices of three cues: the previous cue,
 
        the current cue, and the next cue."""
 
        cur = self.current_cue_index
 
        return [self.bound_index(index) for index in
 
                    (self.prev_pointer or cur - 1, 
 
                     cur, 
 
                     self.next_pointer or cur + 1)]
 
    def get_current_cues(self):
 
        """Returns a list of three cues: the previous cue, the current cue,
 
        and the next cue."""
 
        return [self.get_cue_by_index(index) 
 
            for index in self.get_current_cue_indices()]
 
    def get_cue_by_index(self, index):
 
        if index:
 
        try:
 
            return self.cues[self.bound_index(index)]
 
        else:
 
        except TypeError:
 
            return empty_cue
 
    def __del__(self):
 
        self.save()
 
@@ -379,9 +442,11 @@ class TkCueList(CueList, Tk.Frame):
 
    def __init__(self, master, filename):
 
        CueList.__init__(self, filename)
 
        Tk.Frame.__init__(self, master, bg='black')
 
        self.fader = None
 
        
 
        self.edit_tl = Tk.Toplevel()
 
        self.editor = CueEditron(self.edit_tl, changed_callback=self.redraw_cue)
 
        self.editor = CueEditron(self.edit_tl, 
 
            changed_callback=self.cue_changed)
 
        self.editor.pack(fill='both', expand=1)
 

	
 
        def edit_cue(index):
 
@@ -411,13 +476,16 @@ class TkCueList(CueList, Tk.Frame):
 
        for count, cue in enumerate(self.cues):
 
            self.display_cue(count, cue)
 
        self.update_cue_indicators()
 
    def set_fader(self, fader):
 
        self.fader = fader
 
    def wheelscroll(self, evt):
 
        """Perform mouse wheel scrolling"""
 
        amount = 2
 
        if evt.num == 4:
 
        if evt.num == 4: # scroll down
 
            amount = -2
 
        else:            # scroll up
 
            amount = 2
 
        self.hlist.yview('scroll', amount, 'units')
 
    def redraw_cue(self, cue):
 
    def cue_changed(self, cue):
 
        path = self.cues.index(cue)
 
        for col, header in enumerate(self.columns):
 
            try:
 
@@ -429,6 +497,10 @@ class TkCueList(CueList, Tk.Frame):
 
                self.cue_label_windows[path]['text'] = text
 
            else:
 
                self.hlist.item_configure(path, col, text=text)
 

	
 
        if cue in self.get_current_cues() and self.fader:
 
            self.fader.update_cue_cache()
 
            self.fader.reload_cue_times()
 
    def display_cue(self, path, cue):
 
        for col, header in enumerate(self.columns):
 
            try:
 
@@ -452,6 +524,8 @@ class TkCueList(CueList, Tk.Frame):
 
        """If cue_indices is None, we'll reset all of them."""
 
        cue_indices = cue_indices or self.cue_label_windows.keys()
 
        for key in cue_indices:
 
            if key is None:
 
                continue
 
            window = self.cue_label_windows[key]
 
            window.configure(fg='white', bg='black')
 
    def update_cue_indicators(self):
 
@@ -459,6 +533,8 @@ class TkCueList(CueList, Tk.Frame):
 
                     ('prev', 'cur', 'next')))
 

	
 
        for count, state in states.items():
 
            if count is None:
 
                continue
 
            window = self.cue_label_windows[count]
 
            bg, fg = cue_state_indicator_colors[state]
 
            window.configure(bg=bg, fg=fg)
 
@@ -469,6 +545,7 @@ class TkCueList(CueList, Tk.Frame):
 
        # try to see all indices, but next takes priority over all, and cur
 
        # over prev
 
        for index in self.get_current_cue_indices():
 
            if index is not None:
 
            self.hlist.see(index)
 
    def select_callback(self, index):
 
        new_next = int(index)
 
@@ -514,7 +591,8 @@ class CueEditron(Tk.Frame):
 
                pass
 
    def setup_editing_forms(self):
 
        self.variables = {}
 
        for row, field in enumerate(('name', 'time', 'page', 'desc', 'sub_levels')):
 
        for row, field in enumerate(('name', 'time', 'page', 'desc', 
 
            'sub_levels')):
 
            lab = Tk.Label(self, text=field, fg='white', bg='black')
 
            lab.grid(row=row, column=0, sticky='nsew')
 

	
 
@@ -537,7 +615,8 @@ class CueEditron(Tk.Frame):
 
        self.columnconfigure(1, weight=1)
 
    def fill_in_cue_info(self):
 
        self.enable_callbacks = 0
 
        for row, field in enumerate(('name', 'time', 'page', 'desc', 'sub_levels')):
 
        for row, field in enumerate(('name', 'time', 'page', 'desc', 
 
            'sub_levels')):
 
            text = ''
 
            if self.cue:
 
                try:
flax/cues/cuelist1
Show inline comments
 
<?xml version="1.0"?>
 
<!DOCTYPE PyObject SYSTEM "PyObjects.dtd">
 
<PyObject family="obj" type="builtin_wrapper"  class="_EmptyClass">
 
<attr name="__toplevel__" family="map" type="__compound__" extra="None TreeDict" id="138432956" >
 
<attr name="__toplevel__" family="map" type="__compound__" extra="None TreeDict" id="138506468" >
 
  <entry>
 
    <key type="string" value="cues" />
 
    <val type="list" id="139794108" >
 
      <item type="PyObject" id="140312100" class="Cue">
 
    <val type="list" id="139971548" >
 
      <item type="PyObject" id="140423764" class="Cue">
 
        <attr name="name" type="string" value="tevya special" />
 
        <attr name="desc" type="string" value="whoa - this works" />
 
        <attr name="page" type="string" value="3.2" />
 
        <attr name="name" type="string" value="tevya special" />
 
        <attr name="sub_levels" type="string" value="green : 1.0" />
 
        <attr name="time" type="string" value="0" />
 
        <attr name="time" type="string" value="2" />
 
      </item>
 
      <item type="PyObject" id="139843388" class="Cue">
 
        <attr name="subdict" type="dict" id="140307292" >
 
      <item type="PyObject" id="139862804" class="Cue">
 
        <attr name="subdict" type="dict" id="139863044" >
 
        </attr>
 
        <attr name="name" type="string" value="lady luck" />
 
        <attr name="time" type="string" value="1" />
 
@@ -21,8 +21,8 @@
 
        <attr name="sub_levels" type="string" value="blue : 1.0, green : 0.5" />
 
        <attr name="desc" type="string" value="music flourish" />
 
      </item>
 
      <item type="PyObject" id="139773172" class="Cue">
 
        <attr name="subdict" type="dict" id="139774164" >
 
      <item type="PyObject" id="139862732" class="Cue">
 
        <attr name="subdict" type="dict" id="139852060" >
 
        </attr>
 
        <attr name="name" type="string" value="dolly solo" />
 
        <attr name="time" type="string" value="2" />
 
@@ -30,8 +30,8 @@
 
        <attr name="sub_levels" type="string" value="blue : 0.1, green : 0.1" />
 
        <attr name="desc" type="string" value="tevya: &quot;what&apos;s happening to the tradition?&quot;" />
 
      </item>
 
      <item type="PyObject" id="139793260" class="Cue">
 
        <attr name="subdict" type="dict" id="139774508" >
 
      <item type="PyObject" id="139915236" class="Cue">
 
        <attr name="subdict" type="dict" id="139852964" >
 
        </attr>
 
        <attr name="name" type="string" value="cue 3" />
 
        <attr name="time" type="string" value="4" />
 
@@ -39,17 +39,17 @@
 
        <attr name="sub_levels" type="string" value="red : 1" />
 
        <attr name="desc" type="string" value="the third cue" />
 
      </item>
 
      <item type="PyObject" id="139775180" class="Cue">
 
        <attr name="subdict" type="dict" id="139774764" >
 
      <item type="PyObject" id="139851228" class="Cue">
 
        <attr name="subdict" type="dict" id="139863188" >
 
        </attr>
 
        <attr name="name" type="string" value="heart" />
 
        <attr name="time" type="string" value="42" />
 
        <attr name="time" type="string" value="10" />
 
        <attr name="page" type="string" value="1.3.13" />
 
        <attr name="sub_levels" type="string" value="frontwhite : 0.2, red : 0.7" />
 
        <attr name="desc" type="string" value="&quot;you&apos;ve gotta have heart&quot;" />
 
      </item>
 
      <item type="PyObject" id="140308580" class="Cue">
 
        <attr name="subdict" type="dict" id="140311956" >
 
      <item type="PyObject" id="139863332" class="Cue">
 
        <attr name="subdict" type="dict" id="139841476" >
 
        </attr>
 
        <attr name="name" type="string" value="more musical refs" />
 
        <attr name="time" type="string" value="5" />
 
@@ -57,8 +57,8 @@
 
        <attr name="sub_levels" type="string" value="blue : 1.0" />
 
        <attr name="desc" type="string" value="etc." />
 
      </item>
 
      <item type="PyObject" id="139772700" class="Cue">
 
        <attr name="subdict" type="dict" id="140311684" >
 
      <item type="PyObject" id="139855188" class="Cue">
 
        <attr name="subdict" type="dict" id="139855428" >
 
        </attr>
 
        <attr name="name" type="string" value="rainbow shimmer" />
 
        <attr name="time" type="string" value="6" />
 
@@ -66,8 +66,8 @@
 
        <attr name="sub_levels" type="string" value="" />
 
        <attr name="desc" type="string" value="curtain close" />
 
      </item>
 
      <item type="PyObject" id="139774908" class="Cue">
 
        <attr name="subdict" type="dict" id="140310884" >
 
      <item type="PyObject" id="139873788" class="Cue">
 
        <attr name="subdict" type="dict" id="139855956" >
 
        </attr>
 
        <attr name="name" type="string" value="fade up" />
 
        <attr name="time" type="string" value="7" />
 
@@ -75,8 +75,8 @@
 
        <attr name="sub_levels" type="string" value="" />
 
        <attr name="desc" type="string" value="stage manager: &quot;worklights, please&quot;" />
 
      </item>
 
      <item type="PyObject" id="140311076" class="Cue">
 
        <attr name="subdict" type="dict" id="140310300" >
 
      <item type="PyObject" id="139927324" class="Cue">
 
        <attr name="subdict" type="dict" id="139854356" >
 
        </attr>
 
        <attr name="name" type="string" value="blackout" />
 
        <attr name="time" type="string" value="8" />
 
@@ -84,8 +84,8 @@
 
        <attr name="sub_levels" type="string" value="" />
 
        <attr name="desc" type="string" value="&quot;lights out!&quot;" />
 
      </item>
 
      <item type="PyObject" id="140304700" class="Cue">
 
        <attr name="subdict" type="dict" id="140302268" >
 
      <item type="PyObject" id="139864660" class="Cue">
 
        <attr name="subdict" type="dict" id="139857340" >
 
        </attr>
 
        <attr name="name" type="string" value="sill" />
 
        <attr name="time" type="string" value="4.2" />
 
@@ -93,68 +93,74 @@
 
        <attr name="sub_levels" type="string" value="" />
 
        <attr name="desc" type="string" value="another description" />
 
      </item>
 
      <item type="PyObject" id="140309860" class="Cue">
 
      <item type="PyObject" id="139855916" class="Cue">
 
        <attr name="name" type="string" value="front only" />
 
        <attr name="desc" type="string" value="mr. cue 10" />
 
        <attr name="page" type="string" value="2.7.3" />
 
        <attr name="name" type="string" value="front only" />
 
        <attr name="sub_levels" type="string" value="" />
 
        <attr name="time" type="string" value="10" />
 
      </item>
 
      <item type="PyObject" id="140310788" class="Cue">
 
      <item type="PyObject" id="139163156" class="Cue">
 
        <attr name="name" type="string" value="cue 11" />
 
        <attr name="desc" type="string" value="" />
 
        <attr name="page" type="string" value="" />
 
        <attr name="name" type="string" value="cue 11" />
 
        <attr name="sub_levels" type="string" value="" />
 
        <attr name="time" type="string" value="11" />
 
      </item>
 
      <item type="PyObject" id="139762676" class="Cue">
 
        <attr name="sub_levels" type="string" value="" />
 
      <item type="PyObject" id="139854140" class="Cue">
 
        <attr name="desc" type="string" value="" />
 
        <attr name="page" type="string" value="" />
 
        <attr name="name" type="string" value="cue 12" />
 
        <attr name="sub_levels" type="string" value="" />
 
        <attr name="time" type="string" value="2.1" />
 
      </item>
 
      <item type="PyObject" id="140301540" class="Cue">
 
        <attr name="sub_levels" type="string" value="" />
 
      <item type="PyObject" id="139841764" class="Cue">
 
        <attr name="desc" type="string" value="" />
 
        <attr name="page" type="string" value="" />
 
        <attr name="name" type="string" value="cue 13" />
 
        <attr name="sub_levels" type="string" value="" />
 
        <attr name="time" type="string" value="13" />
 
      </item>
 
      <item type="PyObject" id="140310636" class="Cue">
 
      <item type="PyObject" id="139854308" class="Cue">
 
        <attr name="name" type="string" value="cue 14" />
 
        <attr name="desc" type="string" value="" />
 
        <attr name="page" type="string" value="" />
 
        <attr name="name" type="string" value="cue 14" />
 
        <attr name="sub_levels" type="string" value="red : 1" />
 
        <attr name="time" type="string" value="14" />
 
      </item>
 
      <item type="PyObject" id="140307748" class="Cue">
 
      <item type="PyObject" id="139858580" class="Cue">
 
        <attr name="name" type="string" value="cue 15" />
 
        <attr name="desc" type="string" value="" />
 
        <attr name="page" type="string" value="" />
 
        <attr name="name" type="string" value="cue 15" />
 
        <attr name="sub_levels" type="string" value="red : 1" />
 
        <attr name="time" type="string" value="15" />
 
      </item>
 
      <item type="PyObject" id="140309436" class="Cue">
 
      <item type="PyObject" id="139856100" class="Cue">
 
        <attr name="name" type="string" value="cue 16" />
 
        <attr name="desc" type="string" value="" />
 
        <attr name="page" type="string" value="" />
 
        <attr name="name" type="string" value="cue 16" />
 
        <attr name="sub_levels" type="string" value="red : 1" />
 
        <attr name="time" type="string" value="16" />
 
      </item>
 
      <item type="PyObject" id="140290764" class="Cue">
 
      <item type="PyObject" id="139856180" class="Cue">
 
        <attr name="name" type="string" value="cue 17" />
 
        <attr name="desc" type="string" value="" />
 
        <attr name="page" type="string" value="" />
 
        <attr name="name" type="string" value="cue 17" />
 
        <attr name="sub_levels" type="string" value="red : 1" />
 
        <attr name="time" type="string" value="17" />
 
      </item>
 
      <item type="PyObject" id="140300196" class="Cue">
 
      <item type="PyObject" id="139846156" class="Cue">
 
        <attr name="name" type="string" value="some name" />
 
        <attr name="desc" type="string" value="" />
 
        <attr name="page" type="string" value="" />
 
        <attr name="name" type="string" value="some name" />
 
        <attr name="sub_levels" type="string" value="red : 1" />
 
        <attr name="time" type="string" value="18" />
 
      </item>
 
      <item type="PyObject" id="140301756" class="Cue">
 
      <item type="PyObject" id="139841948" class="Cue">
 
        <attr name="name" type="string" value="cue 19" />
 
        <attr name="desc" type="string" value="" />
 
        <attr name="page" type="string" value="" />
 
        <attr name="name" type="string" value="cue 19" />
 
        <attr name="sub_levels" type="string" value="red : 1" />
 
        <attr name="time" type="string" value="19" />
 
      </item>
 
    </val>
0 comments (0 inline, 0 general)