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