#!/usr/bin/env python3 # -*- coding: utf-8 -*- """OscCommentMacroListener.py: Hog 4 comment macro antlr4 listener for OSC.""" __author__ = "Kevin Matz" __copyright__ = "Copyright 2018, Company 235, LLC" __credits__ = ["Kevin Matz"] __license__ = "MIT" __version__ = "0.0.1" __maintainer__ = "Kevin Matz" __email__ = "kevin@company235.com" __status__ = "Prototype" import antlr4 from CommentMacroParser import CommentMacroParser from CommentMacroListener import CommentMacroListener from OscMacroDefinitions import * from pythonosc import osc_message_builder from pythonosc import udp_client from time import sleep def num(string): try: num = int(string) return num except ValueError: num = float(string) return num # https://raw.githubusercontent.com/jszheng/py3antlr4book/master/bin/pygrun # this is a python version of TestRig def beautify_lisp_string(in_string): __author__ = 'jszheng' indent_size = 2 add_indent = ' ' * indent_size out_string = in_string[0] # no indent for 1st ( indent = '' for i in range(1, len(in_string) - 1): if in_string[i] == '(' and in_string[i + 1] != ' ': indent += add_indent out_string += "\n" + indent + '(' elif in_string[i] == ')': out_string += ')' if len(indent) > 0: indent = indent.replace(add_indent, '', 1) else: out_string += in_string[i] return out_string class OscCommentMacroListener(CommentMacroListener): def __init__(self, parser, server): self.parser = parser self.server = server def button_press(self, device, path, delay=0.05): self.send_message(device, path, 1) # button down sleep(delay) self.send_message(device, path, 0) # button up def send_message(self, device, path, arg): if device is None: osc = list(self.server.values())[0] else: if (device.type.getText() != 'h'): print("Only Hog type devices are curently supported.") print("WARNIN: macro discarded!") return -1 else: try: osc = self.server[device.number.value] except KeyError: print("Net# "+str(device.number.value)+" not configured.") print("WARNING: macro discarded!") return -1 osc.send_message(path, arg) return 1 def exitDevice(self, ctx: CommentMacroParser.DeviceContext): if isinstance(ctx.parentCtx, CommentMacroParser.MacroContext): ctx.parentCtx.device = ctx def enterMacro(self, ctx: CommentMacroParser.MacroContext): ctx.device = None ctx.number = None ctx.master = None ctx.targets = [] ctx.time = None def exitMacro(self, ctx: CommentMacroParser.MacroContext): # print the lisp tree of this macro lisp_tree_str = ctx.toStringTree(recog=self.parser) print(beautify_lisp_string(lisp_tree_str)) # execute macro from name ret = -1 name = ctx.children[0].getText() try: ret = command[name](self, ctx) except KeyError: print(name + " macro is not compatable with OSC.") return -1 print("Exiting Macro") return ret def enterMaster(self, ctx: CommentMacroParser.MasterContext): ctx.targets = [] def exitMaster(self, ctx: CommentMacroParser.MasterContext): ctx.targets = set(ctx.targets) # no duplicates if isinstance(ctx.parentCtx, CommentMacroParser.MacroContext): ctx.parentCtx.master = ctx def exitNumber(self, ctx: CommentMacroParser.NumberContext): ctx.value = num(ctx.getText()) if isinstance(ctx.parentCtx, CommentMacroParser.TargetContext): ctx.parentCtx.targets.append(ctx.value) if isinstance(ctx.parentCtx, CommentMacroParser.MacroContext): ctx.parentCtx.number = ctx if isinstance(ctx.parentCtx, CommentMacroParser.DeviceContext): ctx.parentCtx.number = ctx def exitSpan(self, ctx: CommentMacroParser.SpanContext): number1 = ctx.children[0].value number2 = ctx.children[2].value if (isinstance(number1, int) and isinstance(number2, int)): if isinstance(ctx.parentCtx, CommentMacroParser.TargetContext): minimum = min(number1, number2) maximum = max(number1, number2) for i in (range(minimum, maximum + 1)): ctx.parentCtx.targets.append(i) else: print("ERROR: Spans must be ranged with intigers.") ctx.parentCtx.targets.append(-1) def enterTarget(self, ctx: CommentMacroParser.TargetContext): ctx.targets = [] def exitTarget(self, ctx: CommentMacroParser.TargetContext): ctx.target = set(ctx.targets) # no duplicates ctx.parentCtx.targets.extend(ctx.targets) def exitNodeType(self, ctx: CommentMacroParser.NodeTypeContext): if isinstance(ctx.parentCtx, CommentMacroParser.DeviceContext): ctx.parentCtx.type = ctx