Initial Commit
This commit is contained in:
commit
bb0cbd513e
|
@ -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
|
|
@ -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
|
||||
;
|
|
@ -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
|
|
@ -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)
|
|
@ -0,0 +1,4 @@
|
|||
[hog4]
|
||||
ip: 10.0.0.1
|
||||
port: 6600
|
||||
net: 1
|
Loading…
Reference in New Issue