#!/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__ = "3.9" __maintainer__ = "Kevin Matz" __email__ = "kevin@company235.com" __status__ = "Prototype" import logging from CommentMacroParser import CommentMacroParser from CommentMacroListener import CommentMacroListener from OscMacroDefinitions import HogDevice logger = logging.getLogger("CommentMacro") 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, servers): self.osc = HogDevice(servers) 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=ctx.parser) logger.info(beautify_lisp_string(lisp_tree_str)) # execute macro from name name = ctx.children[0].getText() try: self.osc.command[name](self, ctx) except KeyError: print(name + " macro is not compatable with OSC.") return -1 logger.debug("Exiting Macro") 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: logger.error("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) # add to parent targets def exitNodeType(self, ctx: CommentMacroParser.NodeTypeContext): if isinstance(ctx.parentCtx, CommentMacroParser.DeviceContext): ctx.parentCtx.type = ctx