#!/usr/bin/env python3 # -*- coding: utf-8 -*- """comment.py: Hog 4 comment macro interpreter and OSC bridge.""" __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 configparser import logging import sys from antlr4 import CommonTokenStream from antlr4 import InputStream from antlr4 import ParseTreeWalker from antlr4.error.ErrorListener import ErrorListener from .CommentMacroLexer import CommentMacroLexer from .CommentMacroParser import CommentMacroParser from .OscCommentMacroListener import OscCommentMacroListener from pythonosc import udp_client # define an error listener that raises SyntaxError exceptions class SyntaxErrorListener(ErrorListener): def syntaxError(self, recognizer, offendingSymbol, line, column, msg, e): raise SyntaxError("line "+str(line)+":"+str(column)+" "+msg) # setup logging logger = logging.getLogger(__name__) logger.setLevel(logging.DEBUG) ch = logging.StreamHandler() # create console handler and ch.setLevel(logging.INFO) # set console log level to INFO logger.addHandler(ch) # add console log handler # empty server dictionary servers = {} # open config file config = configparser.ConfigParser(allow_no_value=True) config.read('server.cfg') # set up each hog device for name in config.get('network', 'hogs').split(','): try: # move to config section server = config[name.strip().strip('\"')] # read settings ip = server.get("ip", "10.0.0.100") port = server.getint("port", 7001) net = server.getint("net", 1) # osc clients are added to the dictionary with the net # as the key logger.info("Adding Hog device at net# " + str(net)) servers[net] = udp_client.SimpleUDPClient(ip, port) except KeyError as e: print('Error configuring net#', net, e) continue # clear temp variables off the stack try: del ip, port, net del server, config except NameError as e: print('failed to release memory', e) # init reusable walker and listener walker = ParseTreeWalker() listener = OscCommentMacroListener(servers) # main handler for processing input def comment(text): # force upper case text = text.upper() # generate text stream input_stream = InputStream(text) # lex the text stream lexer = CommentMacroLexer(input_stream) # get token stream from lexer stream = CommonTokenStream(lexer) # parse the token steam parser = CommentMacroParser(stream) # attach an error handler to the parser parser._listeners.append(SyntaxErrorListener()) try: # get tree from parser tree = parser.prog() # walk the tree walker.walk(listener, tree) except SyntaxError as e: logger.debug(e) # antlr internal listener prints the error # # log it to the debug logger anyway # handle user input if run directly if __name__ == '__main__': if len(sys.argv) > 1: # look for macros passed as arguments logger.debug("found macro at argv[1]") comment(sys.argv[1]) else: # for input history and line editing import readline # be an interactive shell while True: # get user input try: text = input("comment# ") except (KeyboardInterrupt, EOFError): text = 'exit' print(text) # catch exit keyword if text.lower() == 'exit': break # exec user input comment(text)