1
0
Fork 0

Initial Commit

This commit is contained in:
Kevin Matz 2018-10-17 20:56:59 -04:00
commit bb0cbd513e
5 changed files with 486 additions and 0 deletions

118
.gitignore vendored Normal file
View File

@ -0,0 +1,118 @@
# Antlr4
.interp
.tokens
CommentMacroLexer.py
CommentMacroListener.py
CommentMacroParser.py
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
.python-version
# celery beat schedule file
celerybeat-schedule
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json

107
CommentMacro.g4 Normal file
View File

@ -0,0 +1,107 @@
grammar CommentMacro;
/** The grammer begins here, as a series of statements. */
prog: statement+ ;
/** Each statement has one or many expressions */
statement
: macro NEWLINE
| NEWLINE
;
macro
: 'GM' master device? // Go Master
| 'GM' master SLASH number device? // Go Master
| 'HM' master device? // Halt Master
| 'AM' master device? // Assert Master
| 'RM' master device? // Relesae Master
| 'RA' device? // Release All
| 'RO' device? // Release Others
| 'FM' master SLASH number time? device? // Fade Master
| 'FGM' number time? device? // Fade Grand Master
| 'CM' number device? // Choose Master
| 'GL' target device? // Go List
| 'GL' target SLASH number device? // Go List
| 'HL' target device? // Halt List
| 'AL' target device? // Assert List
| 'RL' target device? // Release List
| 'GB' target device? // Go Batch
| 'HB' target device? // Halt Batch
| 'AB' target device? // Assert Batch
| 'RB' target device? // Release Batch
| 'GS' target device? // Go Scene
| 'HS' target device? // Halt Scene
| 'AS' target device? // Assert Scene
| 'RS' target device? // Release Scene
| 'CP' number device? // Change Page
| 'CP' NEXT device? // Next Page
| 'CP' PREV device? // Prev Page
| 'RV' number device? // Recall View
| 'RN' device // Reset Node
| 'GK' number device? // Go Keystroke Macro
| 'HK' number device? // Halt Keystroke Macro
| 'RK' number device? // Stop Keystroke Macro
;
master : (target | CURRENT) ;
time : TIME number ;
device : nodeType number ;
number : NUMBER ;
nodeType
: WHOLEHOG
| DP8K
| IOP
;
/** recursive targeting is non-greedy */
target
: ( number | span ) also*?
;
span
: number THRU number
;
also
: ALSO target
;
SLASH : '/' ;
ALSO : ',' ;
THRU : '>' ;
NEXT : '+' ;
PREV : '-' ;
CURRENT : '*' ;
TIME : 't' ;
WHOLEHOG : [hH] ;
DP8K : [dD] ;
IOP : 'IOP';
NUMBER // intigers or floats
: [0-9]+ '.' [0-9]*
| '.' [0-9]+
| [0-9]+
;
NEWLINE // return newlines to parser (end-statement signal)
: '\r'? '\n'
;
WS // ignore whitespace
: [ \t]+
-> skip
;
COMMENT // toss c and HTML sytle block comments
: ( '<!--' .*? '-->'
| '/*' .*? '*/'
) -> skip
;
LINE_COMMENT
: ( '//' ~[\r\n]*
| '#' ~[\r\n]*
) -> skip
;

41
README.md Normal file
View File

@ -0,0 +1,41 @@
# Bacon Script
## Installing
> $ pip install python-osc
Building the lexer and parser for Python3
> $ antlr4 -Dlanguage=Python3 CommentMacro.g4
## Unsupported Macros
These Comment Macros do not have supporting equivelents in OSC:
* Release All
* Release Others
* Master Assert
* List Assert
* Scene Assert
* Batch GO
* Batch Halt
* Batch Assert
* Batch Release
* Node Reset
* Change Page
* Next Page
* Prev Page
* Recall View
* Keystroke Macro Go
* Keystroke Macro Halt
* Keystroke Macro Stop
## Future Work
Pleas feel welcome to submit pull requests or patches that enable support for:
* Sending target ranges as batches
* Multiple comment macros per line
* Send multi-macro line as a batch
* Timing on master fades

216
comment.py Executable file
View File

@ -0,0 +1,216 @@
#!/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__ = "0.0.1"
__maintainer__ = "Kevin Matz"
__email__ = "kevin@company235.com"
__status__ = "Prototype"
import antlr4
import configparser
import readline
import signal
import sys
from CommentMacroLexer import CommentMacroLexer
from CommentMacroParser import CommentMacroParser
from pythonosc import osc_message_builder
from pythonosc import udp_client
from time import sleep
class hog4_osc:
'A Hog 4 OSC device on the network'
def __init__(self, ip, port, net):
self.ip = ip
self.port = port
self.net = net
self.osc = udp_client.SimpleUDPClient(ip, port)
# refactor this to support multiple net#s
config = configparser.ConfigParser(allow_no_value=True)
config.read('server.cfg')
server = config['hog4']
hog4 = hog4_osc(server.get("ip", "10.0.0.1"),
server.getint("port", 6600),
server.getint("net", 1))
def _master_go(expr):
if (expr.master().getText() == "*"):
print("Main GO")
hog4.osc.send_message("/hog/hardware/maingo", 1) # button down
button_delay()
hog4.osc.send_message("/hog/hardware/maingo", 0) # button up
return 1
print("GO Master is a stub")
return -1
def _master_halt(expr):
print("Halt Master is a stub")
return -1
def _master_release(expr):
print("Release Master is a stub")
return -1
def _master_fade(expr):
print("Fade Master is a stub")
return -1
def _master_fade_grand(expr):
try:
level = float(expr.number().getText())
except ValueError:
print("Expected a number...")
return -1
if (level < 0 or level > 100):
print("Level must be between 0 and 100.")
return -1
print("Fading Grand Master to " + str(level) + "%")
level *= 255 / 100 # percent in Macro, 0>255 in OSC
hog4.osc.send_message("/hog/hardware/fader/0", level)
return 1
def _master_choose(expr):
try:
master = int(expr.number().getText())
except ValueError:
print("Expected a number...")
return -1
if (master < 0):
print("Master must be greater than 0.")
return -1
print("Choose Master " + str(master))
hog4.osc.send_message("/hog/hardware/choose/" + str(master), 1) # down
button_delay()
hog4.osc.send_message("/hog/hardware/choose/" + str(master), 0) # up
return 1
def _list_go(expr):
print("Go List is a stub")
return -1
def _list_halt(expr):
print("Halt List is a stub")
return -1
def _list_release(expr):
print("Release List is a stub")
return -1
def _scene_go(expr):
print("Go Scene is a stub")
return -1
def _scene_halt(expr):
print("Halt Scene is a stub")
return -1
def _scene_release(expr):
print("Release Scene is a stub")
return -1
command = {"GM": _master_go,
"HM": _master_halt,
"RM": _master_release,
"FM": _master_fade,
"FGM": _master_fade_grand,
"CM": _master_choose,
"GL": _list_go,
"HL": _list_halt,
"RL": _list_release,
"GS": _scene_go,
"HS": _scene_halt,
"RS": _scene_release
}
def button_delay(time=0.05):
sleep(time)
def comment(text):
input_stream = antlr4.InputStream(text)
lexer = CommentMacroLexer(input_stream)
stream = antlr4.CommonTokenStream(lexer)
parser = CommentMacroParser(stream)
tree = parser.macro()
lisp_tree_str = tree.toStringTree(recog=parser)
print(beautify_lisp_string(lisp_tree_str))
name = tree.children[0].getText()
try:
command[name](tree)
except KeyError:
print(name + " macro is not compatable with OSC.")
return -1
return 1
def orderly_exit(signal=None, frame=None):
print('Goodbye.')
sys.exit(0)
# 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
if __name__ == '__main__':
signal.signal(signal.SIGINT, orderly_exit)
if len(sys.argv) > 1:
comment(sys.argv[1])
else:
while True:
text = input("comment# ")
if text == 'exit':
orderly_exit()
comment(text)

4
server.cfg Normal file
View File

@ -0,0 +1,4 @@
[hog4]
ip: 10.0.0.1
port: 6600
net: 1