Changeset - 1d0fbb6ae089
[Not reviewed]
default
0 1 0
drewp@bigasterisk.com - 6 years ago 2019-06-10 02:29:12
drewp@bigasterisk.com
fix KC sliders support
Ignore-this: c1a285064c54c07266660648a5c8dad
1 file changed with 7 insertions and 5 deletions:
0 comments (0 inline, 0 general)
bin/keyboardcomposer
Show inline comments
 
@@ -280,88 +280,89 @@ class KeyboardComposer(tk.Frame, SubClie
 
        self.stop_frequent_update_time = 0
 

	
 
    def draw_sliders(self):
 
        for r in self.rows:
 
            r.destroy()
 
        self.rows = []
 
        for b in list(self.subbox.values()):
 
            b.cleanup()
 
        self.subbox.clear()
 
        self.slider_table.clear()
 

	
 
        self.tk_focusFollowsMouse()
 

	
 
        rowcount = -1
 
        col = 0
 
        last_group = None
 

	
 
        withgroups = []
 
        for effect in self.graph.subjects(RDF.type, L9['Effect']):
 
            withgroups.append((self.graph.value(effect, L9['group']),
 
                               self.graph.value(effect, L9['order']),
 
                               self.graph.label(effect), effect))
 
        withgroups.sort()
 

	
 
        log.info("withgroups %s", withgroups)
 
        log.debug("withgroups %s", withgroups)
 

	
 
        self.effectEval: Dict[URIRef, light9.effect.effecteval.EffectEval] = {}
 
        imp.reload(light9.effect.effecteval)
 
        simpleOutputs = SimpleOutputs(self.graph)
 
        for group, order, sortLabel, effect in withgroups:
 
            if col == 0 or group != last_group:
 
                row = self.make_row(group)
 
                rowcount += 1
 
                col = 0
 

	
 
            subbox = SubmasterBox(row, self.graph, effect, self.session, col,
 
                                  rowcount)
 
            subbox.place(relx=col / 8, rely=0, relwidth=1 / 8, relheight=1)
 
            self.subbox[effect] = self.slider_table[(rowcount, col)] = subbox
 

	
 
            self.setup_key_nudgers(subbox.scale)
 

	
 
            self.effectEval[effect] = light9.effect.effecteval.EffectEval(
 
                self.graph, effect, simpleOutputs)
 

	
 
            col = (col + 1) % 8
 
            last_group = group
 

	
 
    def toggle_slider_connectedness(self):
 
        self.use_hw_sliders = not self.use_hw_sliders
 
        if self.use_hw_sliders:
 
            self.sliders.reopen()
 
        else:
 
            self.sliders.close()
 
        self.change_row(self.current_row)
 
        self.rows[self.current_row].focus()
 

	
 
    def connect_to_hw(self, hw_sliders):
 
        log.info('connect_to_hw')
 
        if hw_sliders:
 
            try:
 
                self.sliders = Sliders(self)
 
                log.info("connected to sliders")
 
            except IOError:
 
                log.info("no hardware sliders")
 
            except IOError as e:
 
                log.info("no hardware sliders %r", e)
 
                self.sliders = DummySliders()
 
                self.use_hw_sliders = False
 
            dispatcher.connect(self.send_to_hw, 'send_to_hw')
 
        else:
 
            self.sliders = DummySliders()
 

	
 
    def make_key_hints(self):
 
        keyhintrow = tk.Frame(self)
 

	
 
        col = 0
 
        for upkey, downkey in zip(nudge_keys['up'], nudge_keys['down']):
 
            # what a hack!
 
            downkey = downkey.replace('semicolon', ';')
 
            upkey, downkey = (upkey.upper(), downkey.upper())
 

	
 
            # another what a hack!
 
            keylabel = tk.Label(keyhintrow,
 
                                text='%s\n%s' % (upkey, downkey),
 
                                width=1,
 
                                font=('Arial', 10),
 
                                bg='red',
 
                                fg='white',
 
                                anchor='c')
 
            keylabel.pack(side=tk.LEFT, expand=1, fill=tk.X)
 
@@ -448,49 +449,49 @@ class KeyboardComposer(tk.Frame, SubClie
 
        if direction == 'up':
 
            if full:
 
                subbox.scale.fade(1)
 
            else:
 
                subbox.scale.increase()
 
        else:
 
            if full:
 
                subbox.scale.fade(0)
 
            else:
 
                subbox.scale.decrease()
 

	
 
    def hw_slider_moved(self, col, value):
 
        value = int(value * 100) / 100
 
        try:
 
            subbox = self.slider_table[(self.current_row, col)]
 
        except KeyError:
 
            return  # no slider assigned at that column
 

	
 
        if hasattr(self, 'pendingHwSet'):
 
            import twisted.internet.error
 
            try:
 
                self.pendingHwSet.cancel()
 
            except twisted.internet.error.AlreadyCalled:
 
                pass
 
        self.pendingHwSet = reactor.callLater(.01, subbox.safeSliderSet, value)
 
        self.pendingHwSet = reactor.callLater(.01, subbox.setVal, value)
 

	
 
    def send_to_hw(self, sub, hwCol, boxRow):
 
        if isinstance(self.sliders, DummySliders):
 
            return
 

	
 
        assert isinstance(sub, URIRef), repr(sub)
 

	
 
        if boxRow != self.current_row:
 
            return
 

	
 
        try:
 
            level = self.get_levels()[sub]
 
        except KeyError:
 
            log.warn("%r not in %r", sub, self.get_levels())
 
            raise
 
        v = round(127 * level)
 
        chan = "slider%s" % hwCol
 

	
 
        # workaround for some rounding issue, where we receive one
 
        # value and then decide to send back a value that's one step
 
        # lower.  -5 is a fallback for having no last value.  hopefully
 
        # we won't really see it
 
        if abs(v - self.sliders.lastValue.get(chan, -5)) <= 1:
 
            return
 
@@ -603,48 +604,49 @@ class LevelServerHttp(resource.Resource)
 

	
 
    def __init__(self, name_to_subbox):
 
        self.name_to_subbox = name_to_subbox
 

	
 
    def render_POST(self, request):
 
        arg = postArgGetter(request)
 

	
 
        if request.path == '/fadesub':
 
            # fadesub?subname=scoop&level=0&secs=.2
 
            self.name_to_subbox[arg('subname')].scale.fade(
 
                float(arg('level')), float(arg('secs')))
 
            return "set %s to %s" % (arg('subname'), arg('level'))
 
        else:
 
            raise NotImplementedError(repr(request))
 

	
 

	
 
class Sliders(BCF2000):
 

	
 
    def __init__(self, kc):
 
        devices = [
 
            '/dev/snd/midiC3D0', '/dev/snd/midiC2D0', '/dev/snd/midiC1D0'
 
        ]
 
        for dev in devices:
 
            try:
 
                log.info('try sliders on %s', dev)
 
                BCF2000.__init__(self, dev=dev)
 
            except IOError:
 
                if dev is devices[-1]:
 
                    raise
 
            else:
 
                break
 

	
 
        self.kc = kc
 
        log.info('found sliders on %s', dev)
 

	
 
    def valueIn(self, name, value):
 
        kc = self.kc
 
        if name.startswith("slider"):
 
            kc.hw_slider_moved(int(name[6:]) - 1, value / 127)
 
        elif name.startswith("button-upper"):
 
            kc.change_row(kc.current_row)
 
        elif name.startswith("button-lower"):
 
            col = int(name[12:]) - 1
 
            self.valueOut(name, 0)
 
            try:
 
                tkslider = kc.slider_table[(kc.current_row, col)]
 
            except KeyError:
 
                return
 

	
 
@@ -667,44 +669,44 @@ class Sliders(BCF2000):
 

	
 
def launch(opts: Any, root: tk.Tk, graph: SyncedGraph, session: URIRef):
 
    tl = toplevelat("Keyboard Composer - %s" % opts.session,
 
                    existingtoplevel=root,
 
                    graph=graph,
 
                    session=session)
 

	
 
    kc = KeyboardComposer(tl, graph, session, hw_sliders=not opts.no_sliders)
 
    kc.pack(fill=tk.BOTH, expand=1)
 

	
 
    for helpline in ["Bindings: B3 mute"]:
 
        tk.Label(root, text=helpline, font="Helvetica -12 italic",
 
                 anchor='w').pack(side='top', fill='x')
 

	
 

	
 
if __name__ == "__main__":
 
    parser = OptionParser()
 
    parser.add_option('--no-sliders',
 
                      action='store_true',
 
                      help="don't attach to hardware sliders")
 
    clientsession.add_option(parser)
 
    parser.add_option('-v', action='store_true', help="log info level")
 
    opts, args = parser.parse_args()
 

	
 
    log.setLevel(logging.DEBUG if opts.v else logging.WARN)
 
    log.setLevel(logging.DEBUG if opts.v else logging.INFO)
 
    logging.getLogger('colormath').setLevel(logging.INFO)
 

	
 
    graph = SyncedGraph(networking.rdfdb.url, "keyboardcomposer")
 

	
 
    # i think this also needs delayed start (like subcomposer has), to have a valid graph
 
    # before setting any stuff from the ui
 

	
 
    root = tk.Tk()
 
    initTkdnd(root.tk, 'tkdnd/trunk/')
 

	
 
    session = clientsession.getUri('keyboardcomposer', opts)
 

	
 
    graph.initiallySynced.addCallback(lambda _: launch(opts, root, graph,
 
                                                       session))
 

	
 
    root.protocol('WM_DELETE_WINDOW', reactor.stop)
 

	
 
    tksupport.install(root, ms=20)
 
    prof.run(reactor.run, profile=None)
0 comments (0 inline, 0 general)