Compare commits
71 Commits
release-3.
...
master
Author | SHA1 | Date |
---|---|---|
Kevin Matz | 1c499437d7 | |
Kevin Matz | dd452d5c6c | |
Kevin Matz | a34327a874 | |
Kevin Matz | c44effaed9 | |
Kevin Matz | f90bd45e5e | |
Kevin Matz | c392edccf7 | |
Kevin Matz | 8b7ecad7bc | |
Kevin Matz | a2146940f7 | |
Kevin Matz | 784f7df603 | |
Kevin Matz | 19de92834d | |
Kevin Matz | 8056c0098a | |
Kevin Matz | 5c7a2c937a | |
Kevin Matz | 5bf36be3be | |
Kevin Matz | c6cba182d3 | |
Kevin Matz | 75bc47c14e | |
Kevin Matz | 9ccf773ebc | |
Kevin Matz | ef37f016d4 | |
Kevin Matz | 17081bc219 | |
Kevin Matz | fda1ba596e | |
Kevin Matz | 457e53109c | |
Kevin Matz | 9532b1c003 | |
Kevin Matz | 56ea58d7f8 | |
Kevin Matz | d414c8424c | |
Kevin Matz | 28c7abf62a | |
Kevin Matz | 62adeda686 | |
Kevin Matz | 57a432f2bc | |
Kevin Matz | 7fd48be3bc | |
Kevin Matz | b8aec65ee7 | |
Kevin Matz | 3d7b0e13b5 | |
Kevin Matz | 232cd9814b | |
Kevin Matz | a33da15c9f | |
Kevin Matz | 8a0a3b739d | |
Kevin Matz | f9fe9237d0 | |
Kevin Matz | b095913334 | |
Kevin Matz | 92b7be3160 | |
Kevin Matz | 49201ce142 | |
Kevin Matz | 57951e2524 | |
Kevin Matz | d69583c60b | |
Kevin Matz | fcc44e6f49 | |
Kevin Matz | c1a7ad48b2 | |
Kevin Matz | 04994f6804 | |
Kevin Matz | bc1e5920db | |
Kevin Matz | 860088078d | |
Kevin Matz | 31c9c0b5d5 | |
Kevin Matz | 2527b1b0f8 | |
Kevin Matz | 39630e9cde | |
Kevin Matz | 9378112570 | |
Kevin Matz | e7d0a59ccb | |
Kevin Matz | 380621c52b | |
Kevin Matz | f38e5c77ee | |
Kevin Matz | af2bd818da | |
Kevin Matz | 006229f0e0 | |
Kevin Matz | 39410593ee | |
Kevin Matz | 35475a82e0 | |
Kevin Matz | 9e5de3875b | |
Kevin Matz | 95b5510e15 | |
Kevin Matz | 669f4163e9 | |
Kevin Matz | 9fc84b8241 | |
Kevin Matz | b3e7c9c3ef | |
Kevin Matz | 583a3f8a47 | |
Kevin Matz | b807860ab4 | |
Kevin Matz | db0f481769 | |
Kevin Matz | bfe0898f0b | |
Kevin Matz | eb9a0b466d | |
Kevin Matz | 590cb39874 | |
Kevin Matz | 3b48186a79 | |
Kevin Matz | 90209dd49a | |
Kevin Matz | 8e7eb1b8f9 | |
Kevin Matz | 1fa50e0387 | |
Kevin Matz | b114208743 | |
Kevin Matz | 8600af3a9c |
|
@ -1,3 +1,5 @@
|
|||
*.cfg
|
||||
|
||||
# Antlr4
|
||||
*.interp
|
||||
*.tokens
|
||||
|
|
128
CommentMacro.g4
128
CommentMacro.g4
|
@ -1,128 +0,0 @@
|
|||
/*
|
||||
The MIT License (MIT)
|
||||
=====================
|
||||
|
||||
Copyright © 2018 Kevin Matz (kevin@company235.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the “Software”), to deal in the Software without
|
||||
restriction, including without limitation the rights to use,
|
||||
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
grammar CommentMacro;
|
||||
|
||||
/**
|
||||
** Parser Rules
|
||||
**/
|
||||
|
||||
prog : statement+ EOF ;
|
||||
|
||||
statement : macro (':' 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' target (device)? // Go Keystroke Macro
|
||||
| 'HK' target (device)? // Halt Keystroke Macro
|
||||
| 'RK' target (device)? // Stop Keystroke Macro
|
||||
;
|
||||
|
||||
master : (target | CURRENT) ;
|
||||
time : TIME number ;
|
||||
device : nodeType number ;
|
||||
|
||||
nodeType
|
||||
: WHOLEHOG
|
||||
| DP8K
|
||||
| IOP
|
||||
;
|
||||
|
||||
/** recursive targeting is non-greedy */
|
||||
target
|
||||
: ( number | span ) (',' target)*
|
||||
;
|
||||
|
||||
span
|
||||
: number THRU number
|
||||
;
|
||||
|
||||
number : NUMBER ;
|
||||
|
||||
|
||||
/**
|
||||
** LEXAR Rules
|
||||
**/
|
||||
|
||||
fragment DIGIT : [0-9] ;
|
||||
NUMBER : DIGIT+ ('.' DIGIT+)? ;
|
||||
|
||||
SLASH : '/' ;
|
||||
THRU : '>' ;
|
||||
NEXT : '+' ;
|
||||
PREV : '-' ;
|
||||
CURRENT : '*' ;
|
||||
TIME : 't' ;
|
||||
|
||||
WHOLEHOG : [hH] ;
|
||||
DP8K : [dD] ;
|
||||
IOP : 'IOP';
|
||||
|
||||
NEWLINE : '\r'? '\n' ; // return newlines to parser
|
||||
WS : [ \t]+ -> skip ; // ignore whitespace
|
||||
|
||||
COMMENT // toss c and HTML sytle block comments
|
||||
: ( '<!--' .*? '-->'
|
||||
| '/*' .*? '*/'
|
||||
) -> skip
|
||||
;
|
||||
|
||||
LINE_COMMENT // ignore inline commkents
|
||||
: ( '//' ~[\r\n]*
|
||||
| '#' ~[\r\n]*
|
||||
) -> skip
|
||||
;
|
|
@ -1,207 +0,0 @@
|
|||
# Generated from CommentMacro.g4 by ANTLR 4.7.1
|
||||
from antlr4 import *
|
||||
from io import StringIO
|
||||
from typing.io import TextIO
|
||||
import sys
|
||||
|
||||
|
||||
def serializedATN():
|
||||
with StringIO() as buf:
|
||||
buf.write("\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2-")
|
||||
buf.write("\u0111\b\1\4\2\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7")
|
||||
buf.write("\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13\t\13\4\f\t\f\4\r\t\r")
|
||||
buf.write("\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22\4\23")
|
||||
buf.write("\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30")
|
||||
buf.write("\4\31\t\31\4\32\t\32\4\33\t\33\4\34\t\34\4\35\t\35\4\36")
|
||||
buf.write("\t\36\4\37\t\37\4 \t \4!\t!\4\"\t\"\4#\t#\4$\t$\4%\t%")
|
||||
buf.write("\4&\t&\4\'\t\'\4(\t(\4)\t)\4*\t*\4+\t+\4,\t,\4-\t-\3\2")
|
||||
buf.write("\3\2\3\3\3\3\3\3\3\4\3\4\3\4\3\5\3\5\3\5\3\6\3\6\3\6\3")
|
||||
buf.write("\7\3\7\3\7\3\b\3\b\3\b\3\t\3\t\3\t\3\n\3\n\3\n\3\n\3\13")
|
||||
buf.write("\3\13\3\13\3\f\3\f\3\f\3\r\3\r\3\r\3\16\3\16\3\16\3\17")
|
||||
buf.write("\3\17\3\17\3\20\3\20\3\20\3\21\3\21\3\21\3\22\3\22\3\22")
|
||||
buf.write("\3\23\3\23\3\23\3\24\3\24\3\24\3\25\3\25\3\25\3\26\3\26")
|
||||
buf.write("\3\26\3\27\3\27\3\27\3\30\3\30\3\30\3\31\3\31\3\31\3\32")
|
||||
buf.write("\3\32\3\32\3\33\3\33\3\33\3\34\3\34\3\34\3\35\3\35\3\35")
|
||||
buf.write("\3\36\3\36\3\37\3\37\3 \6 \u00b5\n \r \16 \u00b6\3 \3")
|
||||
buf.write(" \6 \u00bb\n \r \16 \u00bc\5 \u00bf\n \3!\3!\3\"\3\"\3")
|
||||
buf.write("#\3#\3$\3$\3%\3%\3&\3&\3\'\3\'\3(\3(\3)\3)\3)\3)\3*\5")
|
||||
buf.write("*\u00d6\n*\3*\3*\3+\6+\u00db\n+\r+\16+\u00dc\3+\3+\3,")
|
||||
buf.write("\3,\3,\3,\3,\3,\7,\u00e7\n,\f,\16,\u00ea\13,\3,\3,\3,")
|
||||
buf.write("\3,\3,\3,\3,\7,\u00f3\n,\f,\16,\u00f6\13,\3,\3,\5,\u00fa")
|
||||
buf.write("\n,\3,\3,\3-\3-\3-\3-\7-\u0102\n-\f-\16-\u0105\13-\3-")
|
||||
buf.write("\3-\7-\u0109\n-\f-\16-\u010c\13-\5-\u010e\n-\3-\3-\4\u00e8")
|
||||
buf.write("\u00f4\2.\3\3\5\4\7\5\t\6\13\7\r\b\17\t\21\n\23\13\25")
|
||||
buf.write("\f\27\r\31\16\33\17\35\20\37\21!\22#\23%\24\'\25)\26+")
|
||||
buf.write("\27-\30/\31\61\32\63\33\65\34\67\359\36;\37=\2? A!C\"")
|
||||
buf.write("E#G$I%K&M\'O(Q)S*U+W,Y-\3\2\7\3\2\62;\4\2JJjj\4\2FFff")
|
||||
buf.write("\4\2\13\13\"\"\4\2\f\f\17\17\2\u011a\2\3\3\2\2\2\2\5\3")
|
||||
buf.write("\2\2\2\2\7\3\2\2\2\2\t\3\2\2\2\2\13\3\2\2\2\2\r\3\2\2")
|
||||
buf.write("\2\2\17\3\2\2\2\2\21\3\2\2\2\2\23\3\2\2\2\2\25\3\2\2\2")
|
||||
buf.write("\2\27\3\2\2\2\2\31\3\2\2\2\2\33\3\2\2\2\2\35\3\2\2\2\2")
|
||||
buf.write("\37\3\2\2\2\2!\3\2\2\2\2#\3\2\2\2\2%\3\2\2\2\2\'\3\2\2")
|
||||
buf.write("\2\2)\3\2\2\2\2+\3\2\2\2\2-\3\2\2\2\2/\3\2\2\2\2\61\3")
|
||||
buf.write("\2\2\2\2\63\3\2\2\2\2\65\3\2\2\2\2\67\3\2\2\2\29\3\2\2")
|
||||
buf.write("\2\2;\3\2\2\2\2?\3\2\2\2\2A\3\2\2\2\2C\3\2\2\2\2E\3\2")
|
||||
buf.write("\2\2\2G\3\2\2\2\2I\3\2\2\2\2K\3\2\2\2\2M\3\2\2\2\2O\3")
|
||||
buf.write("\2\2\2\2Q\3\2\2\2\2S\3\2\2\2\2U\3\2\2\2\2W\3\2\2\2\2Y")
|
||||
buf.write("\3\2\2\2\3[\3\2\2\2\5]\3\2\2\2\7`\3\2\2\2\tc\3\2\2\2\13")
|
||||
buf.write("f\3\2\2\2\ri\3\2\2\2\17l\3\2\2\2\21o\3\2\2\2\23r\3\2\2")
|
||||
buf.write("\2\25v\3\2\2\2\27y\3\2\2\2\31|\3\2\2\2\33\177\3\2\2\2")
|
||||
buf.write("\35\u0082\3\2\2\2\37\u0085\3\2\2\2!\u0088\3\2\2\2#\u008b")
|
||||
buf.write("\3\2\2\2%\u008e\3\2\2\2\'\u0091\3\2\2\2)\u0094\3\2\2\2")
|
||||
buf.write("+\u0097\3\2\2\2-\u009a\3\2\2\2/\u009d\3\2\2\2\61\u00a0")
|
||||
buf.write("\3\2\2\2\63\u00a3\3\2\2\2\65\u00a6\3\2\2\2\67\u00a9\3")
|
||||
buf.write("\2\2\29\u00ac\3\2\2\2;\u00af\3\2\2\2=\u00b1\3\2\2\2?\u00b4")
|
||||
buf.write("\3\2\2\2A\u00c0\3\2\2\2C\u00c2\3\2\2\2E\u00c4\3\2\2\2")
|
||||
buf.write("G\u00c6\3\2\2\2I\u00c8\3\2\2\2K\u00ca\3\2\2\2M\u00cc\3")
|
||||
buf.write("\2\2\2O\u00ce\3\2\2\2Q\u00d0\3\2\2\2S\u00d5\3\2\2\2U\u00da")
|
||||
buf.write("\3\2\2\2W\u00f9\3\2\2\2Y\u010d\3\2\2\2[\\\7<\2\2\\\4\3")
|
||||
buf.write("\2\2\2]^\7I\2\2^_\7O\2\2_\6\3\2\2\2`a\7J\2\2ab\7O\2\2")
|
||||
buf.write("b\b\3\2\2\2cd\7C\2\2de\7O\2\2e\n\3\2\2\2fg\7T\2\2gh\7")
|
||||
buf.write("O\2\2h\f\3\2\2\2ij\7T\2\2jk\7C\2\2k\16\3\2\2\2lm\7T\2")
|
||||
buf.write("\2mn\7Q\2\2n\20\3\2\2\2op\7H\2\2pq\7O\2\2q\22\3\2\2\2")
|
||||
buf.write("rs\7H\2\2st\7I\2\2tu\7O\2\2u\24\3\2\2\2vw\7E\2\2wx\7O")
|
||||
buf.write("\2\2x\26\3\2\2\2yz\7I\2\2z{\7N\2\2{\30\3\2\2\2|}\7J\2")
|
||||
buf.write("\2}~\7N\2\2~\32\3\2\2\2\177\u0080\7C\2\2\u0080\u0081\7")
|
||||
buf.write("N\2\2\u0081\34\3\2\2\2\u0082\u0083\7T\2\2\u0083\u0084")
|
||||
buf.write("\7N\2\2\u0084\36\3\2\2\2\u0085\u0086\7I\2\2\u0086\u0087")
|
||||
buf.write("\7D\2\2\u0087 \3\2\2\2\u0088\u0089\7J\2\2\u0089\u008a")
|
||||
buf.write("\7D\2\2\u008a\"\3\2\2\2\u008b\u008c\7C\2\2\u008c\u008d")
|
||||
buf.write("\7D\2\2\u008d$\3\2\2\2\u008e\u008f\7T\2\2\u008f\u0090")
|
||||
buf.write("\7D\2\2\u0090&\3\2\2\2\u0091\u0092\7I\2\2\u0092\u0093")
|
||||
buf.write("\7U\2\2\u0093(\3\2\2\2\u0094\u0095\7J\2\2\u0095\u0096")
|
||||
buf.write("\7U\2\2\u0096*\3\2\2\2\u0097\u0098\7C\2\2\u0098\u0099")
|
||||
buf.write("\7U\2\2\u0099,\3\2\2\2\u009a\u009b\7T\2\2\u009b\u009c")
|
||||
buf.write("\7U\2\2\u009c.\3\2\2\2\u009d\u009e\7E\2\2\u009e\u009f")
|
||||
buf.write("\7R\2\2\u009f\60\3\2\2\2\u00a0\u00a1\7T\2\2\u00a1\u00a2")
|
||||
buf.write("\7X\2\2\u00a2\62\3\2\2\2\u00a3\u00a4\7T\2\2\u00a4\u00a5")
|
||||
buf.write("\7P\2\2\u00a5\64\3\2\2\2\u00a6\u00a7\7I\2\2\u00a7\u00a8")
|
||||
buf.write("\7M\2\2\u00a8\66\3\2\2\2\u00a9\u00aa\7J\2\2\u00aa\u00ab")
|
||||
buf.write("\7M\2\2\u00ab8\3\2\2\2\u00ac\u00ad\7T\2\2\u00ad\u00ae")
|
||||
buf.write("\7M\2\2\u00ae:\3\2\2\2\u00af\u00b0\7.\2\2\u00b0<\3\2\2")
|
||||
buf.write("\2\u00b1\u00b2\t\2\2\2\u00b2>\3\2\2\2\u00b3\u00b5\5=\37")
|
||||
buf.write("\2\u00b4\u00b3\3\2\2\2\u00b5\u00b6\3\2\2\2\u00b6\u00b4")
|
||||
buf.write("\3\2\2\2\u00b6\u00b7\3\2\2\2\u00b7\u00be\3\2\2\2\u00b8")
|
||||
buf.write("\u00ba\7\60\2\2\u00b9\u00bb\5=\37\2\u00ba\u00b9\3\2\2")
|
||||
buf.write("\2\u00bb\u00bc\3\2\2\2\u00bc\u00ba\3\2\2\2\u00bc\u00bd")
|
||||
buf.write("\3\2\2\2\u00bd\u00bf\3\2\2\2\u00be\u00b8\3\2\2\2\u00be")
|
||||
buf.write("\u00bf\3\2\2\2\u00bf@\3\2\2\2\u00c0\u00c1\7\61\2\2\u00c1")
|
||||
buf.write("B\3\2\2\2\u00c2\u00c3\7@\2\2\u00c3D\3\2\2\2\u00c4\u00c5")
|
||||
buf.write("\7-\2\2\u00c5F\3\2\2\2\u00c6\u00c7\7/\2\2\u00c7H\3\2\2")
|
||||
buf.write("\2\u00c8\u00c9\7,\2\2\u00c9J\3\2\2\2\u00ca\u00cb\7v\2")
|
||||
buf.write("\2\u00cbL\3\2\2\2\u00cc\u00cd\t\3\2\2\u00cdN\3\2\2\2\u00ce")
|
||||
buf.write("\u00cf\t\4\2\2\u00cfP\3\2\2\2\u00d0\u00d1\7K\2\2\u00d1")
|
||||
buf.write("\u00d2\7Q\2\2\u00d2\u00d3\7R\2\2\u00d3R\3\2\2\2\u00d4")
|
||||
buf.write("\u00d6\7\17\2\2\u00d5\u00d4\3\2\2\2\u00d5\u00d6\3\2\2")
|
||||
buf.write("\2\u00d6\u00d7\3\2\2\2\u00d7\u00d8\7\f\2\2\u00d8T\3\2")
|
||||
buf.write("\2\2\u00d9\u00db\t\5\2\2\u00da\u00d9\3\2\2\2\u00db\u00dc")
|
||||
buf.write("\3\2\2\2\u00dc\u00da\3\2\2\2\u00dc\u00dd\3\2\2\2\u00dd")
|
||||
buf.write("\u00de\3\2\2\2\u00de\u00df\b+\2\2\u00dfV\3\2\2\2\u00e0")
|
||||
buf.write("\u00e1\7>\2\2\u00e1\u00e2\7#\2\2\u00e2\u00e3\7/\2\2\u00e3")
|
||||
buf.write("\u00e4\7/\2\2\u00e4\u00e8\3\2\2\2\u00e5\u00e7\13\2\2\2")
|
||||
buf.write("\u00e6\u00e5\3\2\2\2\u00e7\u00ea\3\2\2\2\u00e8\u00e9\3")
|
||||
buf.write("\2\2\2\u00e8\u00e6\3\2\2\2\u00e9\u00eb\3\2\2\2\u00ea\u00e8")
|
||||
buf.write("\3\2\2\2\u00eb\u00ec\7/\2\2\u00ec\u00ed\7/\2\2\u00ed\u00fa")
|
||||
buf.write("\7@\2\2\u00ee\u00ef\7\61\2\2\u00ef\u00f0\7,\2\2\u00f0")
|
||||
buf.write("\u00f4\3\2\2\2\u00f1\u00f3\13\2\2\2\u00f2\u00f1\3\2\2")
|
||||
buf.write("\2\u00f3\u00f6\3\2\2\2\u00f4\u00f5\3\2\2\2\u00f4\u00f2")
|
||||
buf.write("\3\2\2\2\u00f5\u00f7\3\2\2\2\u00f6\u00f4\3\2\2\2\u00f7")
|
||||
buf.write("\u00f8\7,\2\2\u00f8\u00fa\7\61\2\2\u00f9\u00e0\3\2\2\2")
|
||||
buf.write("\u00f9\u00ee\3\2\2\2\u00fa\u00fb\3\2\2\2\u00fb\u00fc\b")
|
||||
buf.write(",\2\2\u00fcX\3\2\2\2\u00fd\u00fe\7\61\2\2\u00fe\u00ff")
|
||||
buf.write("\7\61\2\2\u00ff\u0103\3\2\2\2\u0100\u0102\n\6\2\2\u0101")
|
||||
buf.write("\u0100\3\2\2\2\u0102\u0105\3\2\2\2\u0103\u0101\3\2\2\2")
|
||||
buf.write("\u0103\u0104\3\2\2\2\u0104\u010e\3\2\2\2\u0105\u0103\3")
|
||||
buf.write("\2\2\2\u0106\u010a\7%\2\2\u0107\u0109\n\6\2\2\u0108\u0107")
|
||||
buf.write("\3\2\2\2\u0109\u010c\3\2\2\2\u010a\u0108\3\2\2\2\u010a")
|
||||
buf.write("\u010b\3\2\2\2\u010b\u010e\3\2\2\2\u010c\u010a\3\2\2\2")
|
||||
buf.write("\u010d\u00fd\3\2\2\2\u010d\u0106\3\2\2\2\u010e\u010f\3")
|
||||
buf.write("\2\2\2\u010f\u0110\b-\2\2\u0110Z\3\2\2\2\16\2\u00b6\u00bc")
|
||||
buf.write("\u00be\u00d5\u00dc\u00e8\u00f4\u00f9\u0103\u010a\u010d")
|
||||
buf.write("\3\b\2\2")
|
||||
return buf.getvalue()
|
||||
|
||||
|
||||
class CommentMacroLexer(Lexer):
|
||||
|
||||
atn = ATNDeserializer().deserialize(serializedATN())
|
||||
|
||||
decisionsToDFA = [ DFA(ds, i) for i, ds in enumerate(atn.decisionToState) ]
|
||||
|
||||
T__0 = 1
|
||||
T__1 = 2
|
||||
T__2 = 3
|
||||
T__3 = 4
|
||||
T__4 = 5
|
||||
T__5 = 6
|
||||
T__6 = 7
|
||||
T__7 = 8
|
||||
T__8 = 9
|
||||
T__9 = 10
|
||||
T__10 = 11
|
||||
T__11 = 12
|
||||
T__12 = 13
|
||||
T__13 = 14
|
||||
T__14 = 15
|
||||
T__15 = 16
|
||||
T__16 = 17
|
||||
T__17 = 18
|
||||
T__18 = 19
|
||||
T__19 = 20
|
||||
T__20 = 21
|
||||
T__21 = 22
|
||||
T__22 = 23
|
||||
T__23 = 24
|
||||
T__24 = 25
|
||||
T__25 = 26
|
||||
T__26 = 27
|
||||
T__27 = 28
|
||||
T__28 = 29
|
||||
NUMBER = 30
|
||||
SLASH = 31
|
||||
THRU = 32
|
||||
NEXT = 33
|
||||
PREV = 34
|
||||
CURRENT = 35
|
||||
TIME = 36
|
||||
WHOLEHOG = 37
|
||||
DP8K = 38
|
||||
IOP = 39
|
||||
NEWLINE = 40
|
||||
WS = 41
|
||||
COMMENT = 42
|
||||
LINE_COMMENT = 43
|
||||
|
||||
channelNames = [ u"DEFAULT_TOKEN_CHANNEL", u"HIDDEN" ]
|
||||
|
||||
modeNames = [ "DEFAULT_MODE" ]
|
||||
|
||||
literalNames = [ "<INVALID>",
|
||||
"':'", "'GM'", "'HM'", "'AM'", "'RM'", "'RA'", "'RO'", "'FM'",
|
||||
"'FGM'", "'CM'", "'GL'", "'HL'", "'AL'", "'RL'", "'GB'", "'HB'",
|
||||
"'AB'", "'RB'", "'GS'", "'HS'", "'AS'", "'RS'", "'CP'", "'RV'",
|
||||
"'RN'", "'GK'", "'HK'", "'RK'", "','", "'/'", "'>'", "'+'",
|
||||
"'-'", "'*'", "'t'", "'IOP'" ]
|
||||
|
||||
symbolicNames = [ "<INVALID>",
|
||||
"NUMBER", "SLASH", "THRU", "NEXT", "PREV", "CURRENT", "TIME",
|
||||
"WHOLEHOG", "DP8K", "IOP", "NEWLINE", "WS", "COMMENT", "LINE_COMMENT" ]
|
||||
|
||||
ruleNames = [ "T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6",
|
||||
"T__7", "T__8", "T__9", "T__10", "T__11", "T__12", "T__13",
|
||||
"T__14", "T__15", "T__16", "T__17", "T__18", "T__19",
|
||||
"T__20", "T__21", "T__22", "T__23", "T__24", "T__25",
|
||||
"T__26", "T__27", "T__28", "DIGIT", "NUMBER", "SLASH",
|
||||
"THRU", "NEXT", "PREV", "CURRENT", "TIME", "WHOLEHOG",
|
||||
"DP8K", "IOP", "NEWLINE", "WS", "COMMENT", "LINE_COMMENT" ]
|
||||
|
||||
grammarFileName = "CommentMacro.g4"
|
||||
|
||||
def __init__(self, input=None, output:TextIO = sys.stdout):
|
||||
super().__init__(input, output)
|
||||
self.checkVersion("4.7.1")
|
||||
self._interp = LexerATNSimulator(self, self.atn, self.decisionsToDFA, PredictionContextCache())
|
||||
self._actions = None
|
||||
self._predicates = None
|
||||
|
||||
|
|
@ -1,100 +0,0 @@
|
|||
# Generated from CommentMacro.g4 by ANTLR 4.7.1
|
||||
from antlr4 import *
|
||||
if __name__ is not None and "." in __name__:
|
||||
from .CommentMacroParser import CommentMacroParser
|
||||
else:
|
||||
from CommentMacroParser import CommentMacroParser
|
||||
|
||||
# This class defines a complete listener for a parse tree produced by CommentMacroParser.
|
||||
class CommentMacroListener(ParseTreeListener):
|
||||
|
||||
# Enter a parse tree produced by CommentMacroParser#prog.
|
||||
def enterProg(self, ctx:CommentMacroParser.ProgContext):
|
||||
pass
|
||||
|
||||
# Exit a parse tree produced by CommentMacroParser#prog.
|
||||
def exitProg(self, ctx:CommentMacroParser.ProgContext):
|
||||
pass
|
||||
|
||||
|
||||
# Enter a parse tree produced by CommentMacroParser#statement.
|
||||
def enterStatement(self, ctx:CommentMacroParser.StatementContext):
|
||||
pass
|
||||
|
||||
# Exit a parse tree produced by CommentMacroParser#statement.
|
||||
def exitStatement(self, ctx:CommentMacroParser.StatementContext):
|
||||
pass
|
||||
|
||||
|
||||
# Enter a parse tree produced by CommentMacroParser#macro.
|
||||
def enterMacro(self, ctx:CommentMacroParser.MacroContext):
|
||||
pass
|
||||
|
||||
# Exit a parse tree produced by CommentMacroParser#macro.
|
||||
def exitMacro(self, ctx:CommentMacroParser.MacroContext):
|
||||
pass
|
||||
|
||||
|
||||
# Enter a parse tree produced by CommentMacroParser#master.
|
||||
def enterMaster(self, ctx:CommentMacroParser.MasterContext):
|
||||
pass
|
||||
|
||||
# Exit a parse tree produced by CommentMacroParser#master.
|
||||
def exitMaster(self, ctx:CommentMacroParser.MasterContext):
|
||||
pass
|
||||
|
||||
|
||||
# Enter a parse tree produced by CommentMacroParser#time.
|
||||
def enterTime(self, ctx:CommentMacroParser.TimeContext):
|
||||
pass
|
||||
|
||||
# Exit a parse tree produced by CommentMacroParser#time.
|
||||
def exitTime(self, ctx:CommentMacroParser.TimeContext):
|
||||
pass
|
||||
|
||||
|
||||
# Enter a parse tree produced by CommentMacroParser#device.
|
||||
def enterDevice(self, ctx:CommentMacroParser.DeviceContext):
|
||||
pass
|
||||
|
||||
# Exit a parse tree produced by CommentMacroParser#device.
|
||||
def exitDevice(self, ctx:CommentMacroParser.DeviceContext):
|
||||
pass
|
||||
|
||||
|
||||
# Enter a parse tree produced by CommentMacroParser#nodeType.
|
||||
def enterNodeType(self, ctx:CommentMacroParser.NodeTypeContext):
|
||||
pass
|
||||
|
||||
# Exit a parse tree produced by CommentMacroParser#nodeType.
|
||||
def exitNodeType(self, ctx:CommentMacroParser.NodeTypeContext):
|
||||
pass
|
||||
|
||||
|
||||
# Enter a parse tree produced by CommentMacroParser#target.
|
||||
def enterTarget(self, ctx:CommentMacroParser.TargetContext):
|
||||
pass
|
||||
|
||||
# Exit a parse tree produced by CommentMacroParser#target.
|
||||
def exitTarget(self, ctx:CommentMacroParser.TargetContext):
|
||||
pass
|
||||
|
||||
|
||||
# Enter a parse tree produced by CommentMacroParser#span.
|
||||
def enterSpan(self, ctx:CommentMacroParser.SpanContext):
|
||||
pass
|
||||
|
||||
# Exit a parse tree produced by CommentMacroParser#span.
|
||||
def exitSpan(self, ctx:CommentMacroParser.SpanContext):
|
||||
pass
|
||||
|
||||
|
||||
# Enter a parse tree produced by CommentMacroParser#number.
|
||||
def enterNumber(self, ctx:CommentMacroParser.NumberContext):
|
||||
pass
|
||||
|
||||
# Exit a parse tree produced by CommentMacroParser#number.
|
||||
def exitNumber(self, ctx:CommentMacroParser.NumberContext):
|
||||
pass
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -1,7 +1,4 @@
|
|||
include comment.py
|
||||
include CommentMacroLexer.py
|
||||
include CommentMacroListener.py
|
||||
include CommentMacroParser.py
|
||||
include OscCommentMacroListener.py
|
||||
include LICENSE.md
|
||||
include README.md
|
||||
include examples/example.bs
|
||||
include server.cfg
|
||||
|
|
|
@ -1,115 +0,0 @@
|
|||
#!/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
|
||||
import OscMacroDefinitions
|
||||
from CommentMacroParser import CommentMacroParser
|
||||
from CommentMacroListener import CommentMacroListener
|
||||
|
||||
logger = logging.getLogger("CommentMacro")
|
||||
|
||||
|
||||
# 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 = OscMacroDefinitions.HogDevice(servers)
|
||||
|
||||
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))
|
||||
|
||||
# disallow duplicate targets
|
||||
ctx.targets = set(ctx.targets)
|
||||
|
||||
# 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.")
|
||||
logger.debug("Exiting Macro")
|
||||
|
||||
def enterMaster(self, ctx: CommentMacroParser.MasterContext):
|
||||
ctx.targets = []
|
||||
|
||||
def exitMaster(self, ctx: CommentMacroParser.MasterContext):
|
||||
ctx.parentCtx.master = ctx
|
||||
|
||||
def enterTarget(self, ctx: CommentMacroParser.TargetContext):
|
||||
ctx.targets = []
|
||||
|
||||
def exitTarget(self, ctx: CommentMacroParser.TargetContext):
|
||||
ctx.parentCtx.targets.extend(ctx.targets) # add to parent targets
|
||||
|
||||
def exitNumber(self, ctx: CommentMacroParser.NumberContext):
|
||||
try:
|
||||
ctx.value = int(ctx.getText())
|
||||
except ValueError:
|
||||
ctx.value = float(ctx.getText())
|
||||
|
||||
if isinstance(ctx.parentCtx, CommentMacroParser.TargetContext):
|
||||
ctx.parentCtx.targets.append(ctx.value)
|
||||
else:
|
||||
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)):
|
||||
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.")
|
||||
|
||||
def exitTime(self, ctx: CommentMacroParser.TimeContext):
|
||||
ctx.parentCtx.time = ctx
|
||||
|
||||
def exitDevice(self, ctx: CommentMacroParser.DeviceContext):
|
||||
ctx.parentCtx.device = ctx
|
||||
|
||||
def exitNodeType(self, ctx: CommentMacroParser.NodeTypeContext):
|
||||
ctx.parentCtx.type = ctx.getText()
|
|
@ -1,251 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""OscMacroDefinitions.py: Hog 4 comment macros in OSC for Python3."""
|
||||
|
||||
__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 pythonosc import udp_client
|
||||
from pythonosc import osc_message_builder
|
||||
from pythonosc import osc_bundle_builder
|
||||
from time import sleep
|
||||
|
||||
logger = logging.getLogger("CommentMacro")
|
||||
|
||||
|
||||
class HogDevice():
|
||||
# button state constants
|
||||
buttonDOWN = 1
|
||||
buttonUP = 0
|
||||
|
||||
def __init__(self, servers):
|
||||
self.servers = servers
|
||||
|
||||
def button_press(self, device, path, delay=0.05):
|
||||
self.send_message(device, path, HogDevice.buttonDOWN) # button down
|
||||
sleep(delay)
|
||||
self.send_message(device, path, HogDevice.buttonUP) # button up
|
||||
|
||||
# utility function to send simple messages with one argument
|
||||
def send_message(self, device, path, arg):
|
||||
msg = osc_message_builder.OscMessageBuilder(address=path)
|
||||
msg.add_arg(arg)
|
||||
self.send(device, msg.build())
|
||||
|
||||
# send python-osc messages
|
||||
def send(self, device, msg):
|
||||
if device is None:
|
||||
osc = list(self.servers.values())[0]
|
||||
else:
|
||||
if (device.type != 'h'):
|
||||
logger.error("ERROR: Only Hog type devices are supported.")
|
||||
return
|
||||
else:
|
||||
try:
|
||||
osc = self.servers[device.number.value]
|
||||
except KeyError:
|
||||
logger.error("ERROR: Net# " + str(device.number.value) +
|
||||
" not found.")
|
||||
return
|
||||
try:
|
||||
osc.send(msg)
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
|
||||
def _master_go(self, ctx):
|
||||
if ctx.number is not None:
|
||||
logger.warn("GO MASTER doesn't support goto. " +
|
||||
"Cue number "+str(ctx.number.value)+" is ignored.")
|
||||
if (len(ctx.master.targets) == 0):
|
||||
logger.info("Main GO")
|
||||
self.osc.button_press(ctx.device, "/hog/hardware/maingo")
|
||||
return
|
||||
else:
|
||||
for i in ctx.master.targets:
|
||||
if isinstance(i, int) is not True:
|
||||
logger.warn("GO MASTER macro targets must be intigers. "
|
||||
+ str(i) + " is not an intigers.")
|
||||
continue
|
||||
if (i < 0):
|
||||
logger.warn("Master "+str(i)+" is not greater than 0.")
|
||||
continue
|
||||
master = str(i)
|
||||
logger.info("GO on master " + master)
|
||||
self.osc.button_press(ctx.device, "/hog/hardware/go/" + master)
|
||||
|
||||
def _master_halt(self, ctx):
|
||||
if (len(ctx.master.targets) == 0):
|
||||
logger.info("Main HALT")
|
||||
self.osc.button_press(ctx.device, "/hog/hardware/mainhalt")
|
||||
return
|
||||
else:
|
||||
for i in ctx.master.targets:
|
||||
if isinstance(i, int) is not True:
|
||||
logger.warn("GO MASTER macro targets must be intigers. "
|
||||
+ str(i) + " is not an intigers.")
|
||||
continue
|
||||
if (i < 0):
|
||||
logger.warn("Master "+str(i)+" is not greater than 0.")
|
||||
continue
|
||||
master = str(i)
|
||||
logger.info("HALT on master " + master)
|
||||
self.osc.button_press(ctx.device,
|
||||
"/hog/hardware/pause/" + master)
|
||||
|
||||
def _master_assert(self, ctx):
|
||||
if (len(ctx.master.targets) != 0):
|
||||
logger.error("ERROR: limited to asserting current master only.")
|
||||
return
|
||||
logger.info("ASSERT on current master.")
|
||||
self.osc.button_press(ctx.device, "/hog/hardware/assert")
|
||||
|
||||
def _master_release(self, ctx):
|
||||
if (len(ctx.master.targets) != 0):
|
||||
logger.error("ERROR: limited to releasing current master only.")
|
||||
return
|
||||
logger.info("RELEASE on current master.")
|
||||
self.osc.button_press(ctx.device, "/hog/hardware/release")
|
||||
|
||||
def _master_fade(self, ctx):
|
||||
if (ctx.number) is None:
|
||||
logger.error("ERROR: Missing required argument for LEVEL")
|
||||
return
|
||||
else:
|
||||
level = ctx.number.value
|
||||
if (level < 0 or level > 100):
|
||||
logger.error("Level must be between 0 and 100.")
|
||||
return
|
||||
if (len(ctx.master.targets) == 0):
|
||||
logger.error("MASTER FADE doesn't support * current master.")
|
||||
return
|
||||
else:
|
||||
for i in ctx.master.targets:
|
||||
if isinstance(i, int) is not True:
|
||||
logger.warn("FADE MASTER macro targets must be intigers. "
|
||||
+ str(i) + " is not an intigers.")
|
||||
continue
|
||||
if (i < 0):
|
||||
logger.warn("Master "+str(i)+" is not greater than 0.")
|
||||
continue
|
||||
master = str(i)
|
||||
logger.info("Fade Master "+master+" to "+str(level)+"%")
|
||||
level *= 255 / 100 # percent in Macro, 0>255 in OSC
|
||||
self.osc.send_message(ctx.device,
|
||||
"/hog/hardware/fader/" + master,
|
||||
level)
|
||||
|
||||
def _master_fade_grand(self, ctx):
|
||||
level = ctx.number.value
|
||||
if (level < 0 or level > 100):
|
||||
logger.error("Level must be between 0 and 100.")
|
||||
return
|
||||
logger.info("Fading Grand Master to " + str(level) + "%")
|
||||
level *= 255 / 100 # percent in Macro, 0>255 in OSC
|
||||
self.osc.send_message(ctx.device, "/hog/hardware/fader/0", level)
|
||||
|
||||
def _master_choose(self, ctx):
|
||||
if (ctx.number.value < 0):
|
||||
logger.error("Master must be greater than 0.")
|
||||
return
|
||||
master = str(ctx.number.value)
|
||||
logger.info("Choose Master " + master)
|
||||
self.osc.button_press(ctx.device, "/hog/hardware/choose/" + master)
|
||||
|
||||
def _release_all(self, ctx):
|
||||
logger.info("Release All")
|
||||
self.osc.send_message(ctx.device, "/hog/hardware/pig",
|
||||
HogDevice.buttonDOWN)
|
||||
self.osc.button_press(ctx.device, "/hog/hardware/release")
|
||||
self.osc.send_message(ctx.device, "/hog/hardware/pig",
|
||||
HogDevice.buttonUP)
|
||||
|
||||
def _list_go(self, ctx):
|
||||
for i in ctx.targets:
|
||||
if ctx.number is not None:
|
||||
list = str(i) + "." + str(ctx.number.value)
|
||||
else:
|
||||
list = i
|
||||
logger.info("Go on List " + str(list))
|
||||
self.osc.send_message(ctx.device, "/hog/playback/go/0", list)
|
||||
|
||||
def _list_halt(self, ctx):
|
||||
for i in ctx.targets:
|
||||
logger.info("Halting List " + str(i))
|
||||
self.osc.send_message(ctx.device, "/hog/playback/halt/0", i)
|
||||
|
||||
def _list_release(self, ctx):
|
||||
for i in ctx.targets:
|
||||
logger.info("Releasing List " + str(i))
|
||||
self.osc.send_message(ctx.device, "/hog/playback/release/0", i)
|
||||
|
||||
def _scene_go(self, ctx):
|
||||
for i in ctx.targets:
|
||||
logger.info("Go on Scene " + str(i))
|
||||
self.osc.send_message(ctx.device, "/hog/playback/go/1", i)
|
||||
|
||||
def _scene_halt(self, ctx):
|
||||
for i in ctx.targets:
|
||||
logger.info("Halt Scene " + str(i))
|
||||
self.osc.send_message(ctx.device, "/hog/playback/halt/1", i)
|
||||
|
||||
def _scene_release(self, ctx):
|
||||
for i in ctx.targets:
|
||||
logger.info("Release Scene " + str(i))
|
||||
self.osc.send_message(ctx.device, "/hog/playback/release/1", i)
|
||||
|
||||
def _macro_go(self, ctx):
|
||||
for i in ctx.targets:
|
||||
logger.info("Go on Macro " + str(i))
|
||||
self.osc.send_message(ctx.device, "/hog/playback/go/2", i)
|
||||
|
||||
def _macro_halt(self, ctx):
|
||||
for i in ctx.targets:
|
||||
logger.info("Pause Macro " + str(i))
|
||||
self.osc.send_message(ctx.device, "/hog/playback/halt/2", i)
|
||||
|
||||
def _macro_release(self, ctx):
|
||||
for i in ctx.targets:
|
||||
logger.info("Stop Macro " + str(i))
|
||||
self.osc.send_message(ctx.device, "/hog/playback/release/2", i)
|
||||
|
||||
def _page_change(self, ctx):
|
||||
if ctx.number is not None:
|
||||
logger.error("ERROR: changing page by number is unsupported.")
|
||||
return
|
||||
dir = ctx.children[1].getText()
|
||||
if dir == '+':
|
||||
logger.info("Next Page")
|
||||
self.osc.button_press(ctx.device, "/hog/hardware/nextpage")
|
||||
elif dir == '-':
|
||||
logger.info("Previous Page")
|
||||
self.osc.button_press(ctx.device, "/hog/hardware/backpage")
|
||||
|
||||
command = {"GM": _master_go,
|
||||
"HM": _master_halt,
|
||||
"AM": _master_assert,
|
||||
"RM": _master_release,
|
||||
"FM": _master_fade,
|
||||
"FGM": _master_fade_grand,
|
||||
"CM": _master_choose,
|
||||
"RA": _release_all,
|
||||
"GL": _list_go,
|
||||
"HL": _list_halt,
|
||||
"RL": _list_release,
|
||||
"GS": _scene_go,
|
||||
"HS": _scene_halt,
|
||||
"RS": _scene_release,
|
||||
"GK": _macro_go,
|
||||
"HK": _macro_halt,
|
||||
"RK": _macro_release,
|
||||
"CP": _page_change
|
||||
}
|
35
README.md
35
README.md
|
@ -2,7 +2,7 @@
|
|||
|
||||
A theoretical exercise to control a Hog 4 via OSC, with comment macros.
|
||||
|
||||
The comment macro grammar described in `CommentMacro.g4` is based upon the Hog 3.9 manual, Chapter 22.4. The python3 implementation in `OscMacroDefinitions.py` is based on Chapter 24.2 in the same manual.
|
||||
The comment macro grammar described in `CommentMacro.g4` is based upon the Hog 3.9 manual, Chapter 22.4. The python3 implementation in `OscCommentMacroListener.py` is based on Chapter 24.2 in the same manual.
|
||||
|
||||
Some macros are unsupported/unsupportable with this method. Some macro features, like timing, are not yet implemented. Refer to the **Features** table for specific notes.
|
||||
|
||||
|
@ -29,12 +29,14 @@ Edit `server.cfg` to the correct values for your Hog4.
|
|||
$ ./comment.py
|
||||
Adding Hog device at net# 1
|
||||
comment# GL1
|
||||
(macro GL
|
||||
(target
|
||||
(number 1)))
|
||||
Go on List 1
|
||||
comment# exit
|
||||
Goodbye.
|
||||
```
|
||||
|
||||
Run a baconscript file by passing the script file to `comment.py` as standard input.
|
||||
|
||||
```bash
|
||||
$ ./comment.py < example.bs
|
||||
```
|
||||
|
||||
## Developing
|
||||
|
@ -53,23 +55,26 @@ $ antlr -Dlanguage=Python3 CommentMacro.g4
|
|||
## Features
|
||||
Only features that are supported in both OSC and Comment Macros are able to be
|
||||
implemented in baconscript. This table lists all comment macros (as of 3.9)
|
||||
that are implimented in python.
|
||||
that are implemented in python.
|
||||
|
||||
| Grammar Feature | eg. | Supported |
|
||||
| ----------------|-----|-----------|
|
||||
| fade times | t5 | no |
|
||||
| multiple targets | 1,2 | Yes |
|
||||
| ranges | 1>4 | Yes, integers only |
|
||||
| ranges | 1>4 | Yes, intervals of 1 |
|
||||
| multiple macros | GM1:GL3 | Yes |
|
||||
| network devices | h4 | Yes, H devices only |
|
||||
| wait times | WAIT1 | BaconScript only; Continue script after n seconds.
|
||||
|
||||
Benefiting from the LL(*) parser provided by ANTLR, `multiple targets` and
|
||||
`ranges` may be combined ad infinitum. This is a known deviation from the
|
||||
Comment Macro syntax.
|
||||
|
||||
### Standard Macros
|
||||
|
||||
| Macro | Function | Supported | Notes |
|
||||
|-------|----------|-----------|-------|
|
||||
| GM | Go Master | Yes | |
|
||||
| GM | Go Master | Yes | GOTO on current master only |
|
||||
| HM | Halt Master | Yes | |
|
||||
| AM | Assert Master | Partial | on current master only |
|
||||
| RM | Release Master | Partial | on current master only |
|
||||
|
@ -102,12 +107,24 @@ Comment Macro syntax.
|
|||
| HK | Pause Keystroke Macro | Yes | |
|
||||
| RK | Stop Keystroke Macro | Yes | . |
|
||||
|
||||
### Additional Macros
|
||||
BaconScript also supports several macros that aren't present on Hog4, but become possible/desirable when wrapping OSC.
|
||||
|
||||
| Macro | Function | Notes |
|
||||
|-------|----------|-------|
|
||||
| INT | Select an Intensity Pallet | keypress macro |
|
||||
| POS | Select a Position Pallet | keypress macro |
|
||||
| COLR | Select a Colour Pallet | keypress macro |
|
||||
| BEAM | Select a Beam Pallet | keypress macro |
|
||||
| WAIT | Pause for n seconds | |
|
||||
| PASS | Null instruction | |
|
||||
|
||||
|
||||
## Future Work
|
||||
Pleas feel welcome to submit pull requests or patches that enable support for:
|
||||
|
||||
* Sending target ranges as OSC arguments
|
||||
* Hog4 does not support multiple agruments to a single path.
|
||||
* Hog4 does not support multiple arguments to a single path.
|
||||
* Send multi-macro line as an OSC batch
|
||||
* HogOS 3.9 has a bug involving batches. Whereby only every-other member of the batch will be interpreted.
|
||||
* Timing on master fades
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
"""Init for the baconscript package."""
|
||||
|
||||
from .bacon import (
|
||||
HogNet,
|
||||
beautify_lisp_string,
|
||||
OscCommentMacroListener,
|
||||
SyntaxErrorListener,
|
||||
load_servers,
|
||||
comment,
|
||||
WALKER,
|
||||
LISTENER,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
"HogNet",
|
||||
"beautify_lisp_string",
|
||||
"OscCommentMacroListener",
|
||||
"SyntaxErrorListener",
|
||||
"load_servers",
|
||||
"comment",
|
||||
"WALKER",
|
||||
"LISTENER",
|
||||
]
|
|
@ -0,0 +1,311 @@
|
|||
"""OscCommentMacroListener.py: Hog 4 comment macro antlr4 listener for OSC."""
|
||||
|
||||
import logging
|
||||
from time import sleep
|
||||
|
||||
from .commentmacro.CommentMacroParser import CommentMacroParser
|
||||
from .commentmacro.CommentMacroListener import CommentMacroListener
|
||||
|
||||
__all__ = [
|
||||
"beautify_lisp_string",
|
||||
"OscCommentMacroListener",
|
||||
]
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
# https://raw.githubusercontent.com/jszheng/py3antlr4book/master/bin/pygrun
|
||||
# this is a python version of TestRig
|
||||
def beautify_lisp_string(in_string):
|
||||
"""Prety output of a lisp 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):
|
||||
"""antlr4 listener for comment macros."""
|
||||
|
||||
def __init__(self):
|
||||
"""Initialize the listener."""
|
||||
self.osc = None
|
||||
|
||||
def exitWait(self, ctx: CommentMacroParser.WaitContext):
|
||||
"""On exiting the WAIT macro."""
|
||||
log.info("Waiting %d seconds.", ctx.number().value)
|
||||
sleep(ctx.number().value)
|
||||
|
||||
def enterStatement(self, ctx: CommentMacroParser.StatementContext):
|
||||
"""On entering a statement."""
|
||||
# print the lisp tree of this macro
|
||||
lisp_tree_str = ctx.toStringTree(recog=ctx.parser)
|
||||
log.debug(beautify_lisp_string(lisp_tree_str))
|
||||
|
||||
def enterTarget(self, ctx: CommentMacroParser.TargetContext):
|
||||
"""On entering a target."""
|
||||
ctx.targets = []
|
||||
|
||||
def exitTarget(self, ctx: CommentMacroParser.TargetContext):
|
||||
"""On exiting a target."""
|
||||
ctx.targets = set(ctx.targets)
|
||||
if isinstance(ctx.parentCtx, CommentMacroParser.TargetContext):
|
||||
ctx.parentCtx.targets.extend(ctx.targets) # add to parent targets
|
||||
|
||||
def exitNumber(self, ctx: CommentMacroParser.NumberContext):
|
||||
"""On exiting a number."""
|
||||
try:
|
||||
ctx.value = int(ctx.getText())
|
||||
except ValueError:
|
||||
ctx.value = float(ctx.getText())
|
||||
if isinstance(ctx.parentCtx, CommentMacroParser.TargetContext):
|
||||
ctx.parentCtx.targets.append(ctx.value)
|
||||
|
||||
def exitSpan(self, ctx: CommentMacroParser.SpanContext):
|
||||
"""On exiting a span."""
|
||||
lower = min(ctx.n1.value, ctx.n2.value)
|
||||
upper = max(ctx.n1.value, ctx.n2.value)
|
||||
while lower <= upper:
|
||||
ctx.parentCtx.targets.append(lower)
|
||||
lower += 1
|
||||
|
||||
def exitMasterGo(self, ctx: CommentMacroParser.MasterGoContext):
|
||||
"""On exiting a Go macro."""
|
||||
if ctx.target() is None:
|
||||
log.info("Main GO")
|
||||
self.osc.button_press(ctx.device(), "/hog/hardware/maingo")
|
||||
return
|
||||
for i in ctx.target().targets:
|
||||
if isinstance(i, int) is not True:
|
||||
log.error("GO MASTER macro targets must be intigers.")
|
||||
continue
|
||||
if i < 0:
|
||||
log.error("Master %d is not greater than 0.", i)
|
||||
continue
|
||||
master = str(i)
|
||||
log.info("GO on master %s", master)
|
||||
self.osc.button_press(ctx.device(), "/hog/hardware/go/" + master)
|
||||
|
||||
def exitMasterGoto(self, ctx: CommentMacroParser.MasterGotoContext):
|
||||
"""On exiting a GOTO macro."""
|
||||
if ctx.target() is not None:
|
||||
log.error("ERROR: limited to GOTO on current master only.")
|
||||
return
|
||||
log.info("GOTO on current master.")
|
||||
cue = str(ctx.number().value)
|
||||
self.osc.button_press(ctx.device(), self.osc.buttonMap["goto"])
|
||||
self.osc.number_entry(ctx.device(), cue)
|
||||
self.osc.button_press(ctx.device(), self.osc.buttonMap["enter"])
|
||||
|
||||
def exitMasterHalt(self, ctx: CommentMacroParser.MasterHaltContext):
|
||||
"""On exiting a Master Halt macro."""
|
||||
if ctx.target() is None:
|
||||
log.info("Main HALT")
|
||||
self.osc.button_press(ctx.device(), "/hog/hardware/mainhalt")
|
||||
return
|
||||
for i in ctx.target().targets:
|
||||
if isinstance(i, int) is not True:
|
||||
log.error("GO MASTER macro targets must be intigers.")
|
||||
continue
|
||||
if i < 0:
|
||||
log.error("Master %d is not greater than 0.", i)
|
||||
continue
|
||||
master = str(i)
|
||||
log.info("HALT on master %s", master)
|
||||
self.osc.button_press(ctx.device(), "/hog/hardware/pause/"+master)
|
||||
|
||||
def exitMasterAssert(self, ctx: CommentMacroParser.MasterAssertContext):
|
||||
"""On exiting a Master Assert macro."""
|
||||
if ctx.target() is not None:
|
||||
log.error("ERROR: limited to asserting current master only.")
|
||||
return
|
||||
log.info("ASSERT on current master.")
|
||||
self.osc.button_press(ctx.device(), "/hog/hardware/assert")
|
||||
|
||||
def exitMasterRelease(self, ctx: CommentMacroParser.MasterReleaseContext):
|
||||
"""On exiting a Master Release macro."""
|
||||
if ctx.target() is not None:
|
||||
log.error("ERROR: limited to releasing current master only.")
|
||||
return
|
||||
log.info("RELEASE on current master.")
|
||||
self.osc.button_press(ctx.device(), "/hog/hardware/release")
|
||||
|
||||
def exitMasterFade(self, ctx: CommentMacroParser.MasterFadeContext):
|
||||
"""On exiting a Master Fade macro."""
|
||||
if ctx.target() is None:
|
||||
log.error("ERROR: limited to fading specified masters only.")
|
||||
return
|
||||
level = ctx.number().value
|
||||
if (level < 0 or level > 100):
|
||||
log.error("Level must be between 0 and 100.")
|
||||
return
|
||||
for i in ctx.target().targets:
|
||||
if isinstance(i, int) is not True:
|
||||
log.error("FADE MASTER macro targets must be intigers.")
|
||||
continue
|
||||
if i < 0:
|
||||
log.error("Master %d is not greater than 0.", i)
|
||||
continue
|
||||
master = str(i)
|
||||
log.info("Fade Master %s to %d", master, level)
|
||||
level *= 255 / 100 # percent in Macro, 0>255 in OSC
|
||||
self.osc.send_message(ctx.device(),
|
||||
"/hog/hardware/fader/" + master,
|
||||
level)
|
||||
|
||||
def exitFadeGrandMaster(self,
|
||||
ctx: CommentMacroParser.FadeGrandMasterContext):
|
||||
"""On exiting a GM Fade Macro."""
|
||||
level = ctx.number().value
|
||||
if (level < 0 or level > 100):
|
||||
log.error("Level must be between 0 and 100.")
|
||||
return
|
||||
log.info("Fading Grand Master to %d", level)
|
||||
level *= 255 / 100 # percent in Macro, 0>255 in OSC
|
||||
self.osc.send_message(ctx.device(), "/hog/hardware/fader/0", level)
|
||||
|
||||
def exitMasterChoose(self, ctx: CommentMacroParser.MasterChooseContext):
|
||||
"""On exiting a Master Choose macro."""
|
||||
if ctx.number().value < 0:
|
||||
log.error("Master must be greater than 0.")
|
||||
return
|
||||
master = str(ctx.number().value)
|
||||
log.info("Choose Master %s", master)
|
||||
self.osc.button_press(ctx.device(), "/hog/hardware/choose/" + master)
|
||||
|
||||
def exitReleaseAll(self, ctx: CommentMacroParser.ReleaseAllContext):
|
||||
"""On exiting a Release All Macro."""
|
||||
log.info("Release All")
|
||||
self.osc.send_message(ctx.device(), "/hog/hardware/pig",
|
||||
self.osc.buttonDOWN)
|
||||
self.osc.button_press(ctx.device(), "/hog/hardware/release")
|
||||
self.osc.send_message(ctx.device(), "/hog/hardware/pig",
|
||||
self.osc.buttonUP)
|
||||
|
||||
def exitListGo(self, ctx: CommentMacroParser.ListGoContext):
|
||||
"""On exiting a List GO macro."""
|
||||
for i in ctx.target().targets:
|
||||
log.info("Go on List %d", i)
|
||||
self.osc.send_message(ctx.device(), "/hog/playback/go/0", i)
|
||||
|
||||
def exitListGoto(self, ctx: CommentMacroParser.ListGotoContext):
|
||||
"""On exiting a GOTO macro."""
|
||||
for i in ctx.target().targets:
|
||||
cuelist = str(i) + "." + str(ctx.number().value)
|
||||
log.info("Go on List %s", cuelist)
|
||||
self.osc.send_message(ctx.device(), "/hog/playback/go/0", list)
|
||||
|
||||
def exitListHalt(self, ctx: CommentMacroParser.ListHaltContext):
|
||||
"""On exiting a Halt macro."""
|
||||
for i in ctx.target().targets:
|
||||
log.info("Halting List %d", i)
|
||||
self.osc.send_message(ctx.device(), "/hog/playback/halt/0", i)
|
||||
|
||||
def exitListRelese(self, ctx: CommentMacroParser.ListReleseContext):
|
||||
"""On exiting a Release macro."""
|
||||
for i in ctx.target().targets:
|
||||
log.info("Releasing List %d", i)
|
||||
self.osc.send_message(ctx.device(), "/hog/playback/release/0", i)
|
||||
|
||||
def exitSceneGo(self, ctx: CommentMacroParser.SceneGoContext):
|
||||
"""On exiting a Scene GO macro."""
|
||||
for i in ctx.target().targets:
|
||||
log.info("Go on Scene %d", i)
|
||||
self.osc.send_message(ctx.device(), "/hog/playback/go/1", i)
|
||||
|
||||
def exitSceneHalt(self, ctx: CommentMacroParser.SceneHaltContext):
|
||||
"""On exiting a Scene Halt macro."""
|
||||
for i in ctx.target().targets:
|
||||
log.info("Halt Scene %d", i)
|
||||
self.osc.send_message(ctx.device(), "/hog/playback/halt/1", i)
|
||||
|
||||
def exitSceneRelease(self, ctx: CommentMacroParser.SceneReleaseContext):
|
||||
"""On exiting a Scene Release macro."""
|
||||
for i in ctx.target().targets:
|
||||
log.info("Release Scene %d", i)
|
||||
self.osc.send_message(ctx.device(), "/hog/playback/release/1", i)
|
||||
|
||||
def exitMacroGo(self, ctx: CommentMacroParser.MacroGoContext):
|
||||
"""On exiting a Macro GO macro."""
|
||||
for i in ctx.target().targets:
|
||||
log.info("Go on Macro %d", i)
|
||||
self.osc.send_message(ctx.device(), "/hog/playback/go/2", i)
|
||||
|
||||
def exitMacroHalt(self, ctx: CommentMacroParser.MacroHaltContext):
|
||||
"""On exiting a Macro Halt macro."""
|
||||
for i in ctx.target().targets:
|
||||
log.info("Pause Macro %d", i)
|
||||
self.osc.send_message(ctx.device(), "/hog/playback/halt/2", i)
|
||||
|
||||
def exitMacroStop(self, ctx: CommentMacroParser.MacroStopContext):
|
||||
"""On exiting a Macro Stop macro."""
|
||||
for i in ctx.target().targets:
|
||||
log.info("Stop Macro %d", i)
|
||||
self.osc.send_message(ctx.device(), "/hog/playback/release/2", i)
|
||||
|
||||
def exitPageNext(self, ctx: CommentMacroParser.PageNextContext):
|
||||
"""On exiting a Next Page macro."""
|
||||
log.info("Next Page")
|
||||
self.osc.button_press(ctx.device(), "/hog/hardware/nextpage")
|
||||
|
||||
def exitPagePrev(self, ctx: CommentMacroParser.PagePrevContext):
|
||||
"""On exiting a Previous Page macro."""
|
||||
log.info("Prev Page")
|
||||
self.osc.button_press(ctx.device(), "/hog/hardware/backpage")
|
||||
|
||||
def exitSelectIntensity(self,
|
||||
ctx: CommentMacroParser.SelectIntensityContext):
|
||||
"""On exiting a Select Intensity macro."""
|
||||
if ctx.number().value < 0:
|
||||
log.error("Pallet must be greater than 0.")
|
||||
return
|
||||
pallet = str(ctx.number().value)
|
||||
log.info("Selecting intensity pallet %s", pallet)
|
||||
self.osc.button_press(ctx.device(), self.osc.buttonMap["intensity"])
|
||||
self.osc.number_entry(ctx.device(), pallet)
|
||||
self.osc.button_press(ctx.device(), self.osc.buttonMap["enter"])
|
||||
|
||||
def exitSelectPosition(self,
|
||||
ctx: CommentMacroParser.SelectPositionContext):
|
||||
"""On exiting a Select Intensity macro."""
|
||||
if ctx.number().value < 0:
|
||||
log.error("Pallet must be greater than 0.")
|
||||
return
|
||||
pallet = str(ctx.number().value)
|
||||
log.info("Selecting position pallet %s", pallet)
|
||||
self.osc.button_press(ctx.device(), self.osc.buttonMap["position"])
|
||||
self.osc.number_entry(ctx.device(), pallet)
|
||||
self.osc.button_press(ctx.device(), self.osc.buttonMap["enter"])
|
||||
|
||||
def exitSelectColour(self, ctx: CommentMacroParser.SelectColourContext):
|
||||
"""On exiting a Select Intensity macro."""
|
||||
if ctx.number().value < 0:
|
||||
log.error("Pallet must be greater than 0.")
|
||||
return
|
||||
pallet = str(ctx.number().value)
|
||||
log.info("Selecting colour pallet %s", pallet)
|
||||
self.osc.button_press(ctx.device(), self.osc.buttonMap["colour"])
|
||||
self.osc.number_entry(ctx.device(), pallet)
|
||||
self.osc.button_press(ctx.device(), self.osc.buttonMap["enter"])
|
||||
|
||||
def exitSelectBeam(self, ctx: CommentMacroParser.SelectBeamContext):
|
||||
"""On exiting a Select Intensity macro."""
|
||||
if ctx.number().value < 0:
|
||||
log.error("Pallet must be greater than 0.")
|
||||
return
|
||||
pallet = str(ctx.number().value)
|
||||
log.info("Selecting beam pallet %s", pallet)
|
||||
self.osc.button_press(ctx.device(), self.osc.buttonMap["beam"])
|
||||
self.osc.number_entry(ctx.device(), pallet)
|
||||
self.osc.button_press(ctx.device(), self.osc.buttonMap["enter"])
|
|
@ -0,0 +1,28 @@
|
|||
"""Main BaconScript module init."""
|
||||
|
||||
from .hog4 import HogNet
|
||||
from .OscListener import beautify_lisp_string, OscCommentMacroListener
|
||||
from .script import (
|
||||
SyntaxErrorListener,
|
||||
load_servers,
|
||||
comment,
|
||||
WALKER,
|
||||
LISTENER
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
"HogNet",
|
||||
]
|
||||
|
||||
__all__ += [
|
||||
"beautify_lisp_string",
|
||||
"OscCommentMacroListener",
|
||||
]
|
||||
|
||||
__all__ = [
|
||||
"SyntaxErrorListener",
|
||||
"load_servers",
|
||||
"comment",
|
||||
"WALKER",
|
||||
"LISTENER",
|
||||
]
|
|
@ -0,0 +1,125 @@
|
|||
/*
|
||||
The MIT License (MIT)
|
||||
=====================
|
||||
|
||||
Copyright © 2018 Kevin Matz (kevin@company235.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the “Software”), to deal in the Software without
|
||||
restriction, including without limitation the rights to use,
|
||||
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
grammar CommentMacro;
|
||||
|
||||
/**
|
||||
** Parser Rules
|
||||
**/
|
||||
|
||||
prog : statement* EOF;
|
||||
|
||||
|
||||
statement : macro (':' macro)* NEWLINE?
|
||||
| NEWLINE
|
||||
;
|
||||
|
||||
macro
|
||||
: 'GM' ( target | '*' ) device? #MasterGo
|
||||
| 'GM' ( target | '*' ) '/' number device? #MasterGoto
|
||||
| 'HM' ( target | '*' ) device? #MasterHalt
|
||||
| 'AM' ( target | '*' ) device? #MasterAssert
|
||||
| 'RM' ( target | '*' ) device? #MasterRelease
|
||||
| 'RA' device? #ReleaseAll
|
||||
| 'RO' device? #ReleaseOthers
|
||||
| 'FM' ( target | '*' ) '/' number time? device? #MasterFade
|
||||
| 'FGM' number time? device? #FadeGrandMaster
|
||||
| 'CM' number device? #MasterChoose
|
||||
| 'GL' target device? #ListGo
|
||||
| 'GL' target '/' number device? #ListGoto
|
||||
| 'HL' target device? #ListHalt
|
||||
| 'AL' target device? #ListAssert
|
||||
| 'RL' target device? #ListRelese
|
||||
| 'GB' target device? #BatchGo
|
||||
| 'HB' target device? #BatchHalt
|
||||
| 'AB' target device? #BatchAssert
|
||||
| 'RB' target device? #BatchRelease
|
||||
| 'GS' target device? #SceneGo
|
||||
| 'HS' target device? #SceneHalt
|
||||
| 'AS' target device? #SceneAssert
|
||||
| 'RS' target device? #SceneRelease
|
||||
| 'CP' number device? #PageChange
|
||||
| 'CP' '+' device? #PageNext
|
||||
| 'CP' '-' device? #PagePrev
|
||||
| 'RV' number device? #RecallView
|
||||
| 'RN' device #NodeReset
|
||||
| 'GK' target device? #MacroGo
|
||||
| 'HK' target device? #MacroHalt
|
||||
| 'RK' target device? #MacroStop
|
||||
| 'INT' number device? #SelectIntensity
|
||||
| 'POS' number device? #SelectPosition
|
||||
| 'COLR' number device? #SelectColour
|
||||
| 'BEAM' number device? #SelectBeam
|
||||
| 'WAIT' number #Wait
|
||||
| 'PASS' #Pass
|
||||
;
|
||||
|
||||
time : TIME number ;
|
||||
device : nodeType number ;
|
||||
|
||||
nodeType
|
||||
: WHOLEHOG
|
||||
| DP8K
|
||||
| IOP
|
||||
;
|
||||
|
||||
/** recursive targeting is non-greedy */
|
||||
target
|
||||
: ( number | span ) (',' target)*
|
||||
;
|
||||
|
||||
span
|
||||
: n1=number THRU n2=number
|
||||
;
|
||||
|
||||
number : NUMBER ;
|
||||
|
||||
|
||||
/**
|
||||
** LEXAR Rules
|
||||
**/
|
||||
|
||||
fragment DIGIT : [0-9] ;
|
||||
NUMBER : DIGIT+ ('.' DIGIT+)? ;
|
||||
|
||||
THRU : '>' ;
|
||||
CURRENT : '*' ;
|
||||
TIME : 't' ;
|
||||
|
||||
WHOLEHOG : [hH] ;
|
||||
DP8K : [dD] ;
|
||||
IOP : 'IOP';
|
||||
|
||||
NEWLINE : '\r'? '\n' ; // return newlines to parser
|
||||
WS : [ \t]+ -> skip ; // ignore whitespace
|
||||
|
||||
COMMENT // ignore inline commkents
|
||||
: ( '//' ~[\r\n]*
|
||||
| '#' ~[\r\n]*
|
||||
) -> skip
|
||||
;
|
|
@ -0,0 +1,201 @@
|
|||
# Generated from CommentMacro.g4 by ANTLR 4.10.1
|
||||
from antlr4 import *
|
||||
from io import StringIO
|
||||
import sys
|
||||
if sys.version_info[1] > 5:
|
||||
from typing import TextIO
|
||||
else:
|
||||
from typing.io import TextIO
|
||||
|
||||
|
||||
def serializedATN():
|
||||
return [
|
||||
4,0,48,280,6,-1,2,0,7,0,2,1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5,
|
||||
2,6,7,6,2,7,7,7,2,8,7,8,2,9,7,9,2,10,7,10,2,11,7,11,2,12,7,12,2,
|
||||
13,7,13,2,14,7,14,2,15,7,15,2,16,7,16,2,17,7,17,2,18,7,18,2,19,7,
|
||||
19,2,20,7,20,2,21,7,21,2,22,7,22,2,23,7,23,2,24,7,24,2,25,7,25,2,
|
||||
26,7,26,2,27,7,27,2,28,7,28,2,29,7,29,2,30,7,30,2,31,7,31,2,32,7,
|
||||
32,2,33,7,33,2,34,7,34,2,35,7,35,2,36,7,36,2,37,7,37,2,38,7,38,2,
|
||||
39,7,39,2,40,7,40,2,41,7,41,2,42,7,42,2,43,7,43,2,44,7,44,2,45,7,
|
||||
45,2,46,7,46,2,47,7,47,2,48,7,48,1,0,1,0,1,1,1,1,1,1,1,2,1,2,1,3,
|
||||
1,3,1,3,1,4,1,4,1,4,1,5,1,5,1,5,1,6,1,6,1,6,1,7,1,7,1,7,1,8,1,8,
|
||||
1,8,1,9,1,9,1,9,1,9,1,10,1,10,1,10,1,11,1,11,1,11,1,12,1,12,1,12,
|
||||
1,13,1,13,1,13,1,14,1,14,1,14,1,15,1,15,1,15,1,16,1,16,1,16,1,17,
|
||||
1,17,1,17,1,18,1,18,1,18,1,19,1,19,1,19,1,20,1,20,1,20,1,21,1,21,
|
||||
1,21,1,22,1,22,1,22,1,23,1,23,1,23,1,24,1,24,1,25,1,25,1,26,1,26,
|
||||
1,26,1,27,1,27,1,27,1,28,1,28,1,28,1,29,1,29,1,29,1,30,1,30,1,30,
|
||||
1,31,1,31,1,31,1,31,1,32,1,32,1,32,1,32,1,33,1,33,1,33,1,33,1,33,
|
||||
1,34,1,34,1,34,1,34,1,34,1,35,1,35,1,35,1,35,1,35,1,36,1,36,1,36,
|
||||
1,36,1,36,1,37,1,37,1,38,1,38,1,39,4,39,223,8,39,11,39,12,39,224,
|
||||
1,39,1,39,4,39,229,8,39,11,39,12,39,230,3,39,233,8,39,1,40,1,40,
|
||||
1,41,1,41,1,42,1,42,1,43,1,43,1,44,1,44,1,45,1,45,1,45,1,45,1,46,
|
||||
3,46,250,8,46,1,46,1,46,1,47,4,47,255,8,47,11,47,12,47,256,1,47,
|
||||
1,47,1,48,1,48,1,48,1,48,5,48,265,8,48,10,48,12,48,268,9,48,1,48,
|
||||
1,48,5,48,272,8,48,10,48,12,48,275,9,48,3,48,277,8,48,1,48,1,48,
|
||||
0,0,49,1,1,3,2,5,3,7,4,9,5,11,6,13,7,15,8,17,9,19,10,21,11,23,12,
|
||||
25,13,27,14,29,15,31,16,33,17,35,18,37,19,39,20,41,21,43,22,45,23,
|
||||
47,24,49,25,51,26,53,27,55,28,57,29,59,30,61,31,63,32,65,33,67,34,
|
||||
69,35,71,36,73,37,75,38,77,0,79,39,81,40,83,41,85,42,87,43,89,44,
|
||||
91,45,93,46,95,47,97,48,1,0,5,1,0,48,57,2,0,72,72,104,104,2,0,68,
|
||||
68,100,100,2,0,9,9,32,32,2,0,10,10,13,13,286,0,1,1,0,0,0,0,3,1,0,
|
||||
0,0,0,5,1,0,0,0,0,7,1,0,0,0,0,9,1,0,0,0,0,11,1,0,0,0,0,13,1,0,0,
|
||||
0,0,15,1,0,0,0,0,17,1,0,0,0,0,19,1,0,0,0,0,21,1,0,0,0,0,23,1,0,0,
|
||||
0,0,25,1,0,0,0,0,27,1,0,0,0,0,29,1,0,0,0,0,31,1,0,0,0,0,33,1,0,0,
|
||||
0,0,35,1,0,0,0,0,37,1,0,0,0,0,39,1,0,0,0,0,41,1,0,0,0,0,43,1,0,0,
|
||||
0,0,45,1,0,0,0,0,47,1,0,0,0,0,49,1,0,0,0,0,51,1,0,0,0,0,53,1,0,0,
|
||||
0,0,55,1,0,0,0,0,57,1,0,0,0,0,59,1,0,0,0,0,61,1,0,0,0,0,63,1,0,0,
|
||||
0,0,65,1,0,0,0,0,67,1,0,0,0,0,69,1,0,0,0,0,71,1,0,0,0,0,73,1,0,0,
|
||||
0,0,75,1,0,0,0,0,79,1,0,0,0,0,81,1,0,0,0,0,83,1,0,0,0,0,85,1,0,0,
|
||||
0,0,87,1,0,0,0,0,89,1,0,0,0,0,91,1,0,0,0,0,93,1,0,0,0,0,95,1,0,0,
|
||||
0,0,97,1,0,0,0,1,99,1,0,0,0,3,101,1,0,0,0,5,104,1,0,0,0,7,106,1,
|
||||
0,0,0,9,109,1,0,0,0,11,112,1,0,0,0,13,115,1,0,0,0,15,118,1,0,0,0,
|
||||
17,121,1,0,0,0,19,124,1,0,0,0,21,128,1,0,0,0,23,131,1,0,0,0,25,134,
|
||||
1,0,0,0,27,137,1,0,0,0,29,140,1,0,0,0,31,143,1,0,0,0,33,146,1,0,
|
||||
0,0,35,149,1,0,0,0,37,152,1,0,0,0,39,155,1,0,0,0,41,158,1,0,0,0,
|
||||
43,161,1,0,0,0,45,164,1,0,0,0,47,167,1,0,0,0,49,170,1,0,0,0,51,172,
|
||||
1,0,0,0,53,174,1,0,0,0,55,177,1,0,0,0,57,180,1,0,0,0,59,183,1,0,
|
||||
0,0,61,186,1,0,0,0,63,189,1,0,0,0,65,193,1,0,0,0,67,197,1,0,0,0,
|
||||
69,202,1,0,0,0,71,207,1,0,0,0,73,212,1,0,0,0,75,217,1,0,0,0,77,219,
|
||||
1,0,0,0,79,222,1,0,0,0,81,234,1,0,0,0,83,236,1,0,0,0,85,238,1,0,
|
||||
0,0,87,240,1,0,0,0,89,242,1,0,0,0,91,244,1,0,0,0,93,249,1,0,0,0,
|
||||
95,254,1,0,0,0,97,276,1,0,0,0,99,100,5,58,0,0,100,2,1,0,0,0,101,
|
||||
102,5,71,0,0,102,103,5,77,0,0,103,4,1,0,0,0,104,105,5,47,0,0,105,
|
||||
6,1,0,0,0,106,107,5,72,0,0,107,108,5,77,0,0,108,8,1,0,0,0,109,110,
|
||||
5,65,0,0,110,111,5,77,0,0,111,10,1,0,0,0,112,113,5,82,0,0,113,114,
|
||||
5,77,0,0,114,12,1,0,0,0,115,116,5,82,0,0,116,117,5,65,0,0,117,14,
|
||||
1,0,0,0,118,119,5,82,0,0,119,120,5,79,0,0,120,16,1,0,0,0,121,122,
|
||||
5,70,0,0,122,123,5,77,0,0,123,18,1,0,0,0,124,125,5,70,0,0,125,126,
|
||||
5,71,0,0,126,127,5,77,0,0,127,20,1,0,0,0,128,129,5,67,0,0,129,130,
|
||||
5,77,0,0,130,22,1,0,0,0,131,132,5,71,0,0,132,133,5,76,0,0,133,24,
|
||||
1,0,0,0,134,135,5,72,0,0,135,136,5,76,0,0,136,26,1,0,0,0,137,138,
|
||||
5,65,0,0,138,139,5,76,0,0,139,28,1,0,0,0,140,141,5,82,0,0,141,142,
|
||||
5,76,0,0,142,30,1,0,0,0,143,144,5,71,0,0,144,145,5,66,0,0,145,32,
|
||||
1,0,0,0,146,147,5,72,0,0,147,148,5,66,0,0,148,34,1,0,0,0,149,150,
|
||||
5,65,0,0,150,151,5,66,0,0,151,36,1,0,0,0,152,153,5,82,0,0,153,154,
|
||||
5,66,0,0,154,38,1,0,0,0,155,156,5,71,0,0,156,157,5,83,0,0,157,40,
|
||||
1,0,0,0,158,159,5,72,0,0,159,160,5,83,0,0,160,42,1,0,0,0,161,162,
|
||||
5,65,0,0,162,163,5,83,0,0,163,44,1,0,0,0,164,165,5,82,0,0,165,166,
|
||||
5,83,0,0,166,46,1,0,0,0,167,168,5,67,0,0,168,169,5,80,0,0,169,48,
|
||||
1,0,0,0,170,171,5,43,0,0,171,50,1,0,0,0,172,173,5,45,0,0,173,52,
|
||||
1,0,0,0,174,175,5,82,0,0,175,176,5,86,0,0,176,54,1,0,0,0,177,178,
|
||||
5,82,0,0,178,179,5,78,0,0,179,56,1,0,0,0,180,181,5,71,0,0,181,182,
|
||||
5,75,0,0,182,58,1,0,0,0,183,184,5,72,0,0,184,185,5,75,0,0,185,60,
|
||||
1,0,0,0,186,187,5,82,0,0,187,188,5,75,0,0,188,62,1,0,0,0,189,190,
|
||||
5,73,0,0,190,191,5,78,0,0,191,192,5,84,0,0,192,64,1,0,0,0,193,194,
|
||||
5,80,0,0,194,195,5,79,0,0,195,196,5,83,0,0,196,66,1,0,0,0,197,198,
|
||||
5,67,0,0,198,199,5,79,0,0,199,200,5,76,0,0,200,201,5,82,0,0,201,
|
||||
68,1,0,0,0,202,203,5,66,0,0,203,204,5,69,0,0,204,205,5,65,0,0,205,
|
||||
206,5,77,0,0,206,70,1,0,0,0,207,208,5,87,0,0,208,209,5,65,0,0,209,
|
||||
210,5,73,0,0,210,211,5,84,0,0,211,72,1,0,0,0,212,213,5,80,0,0,213,
|
||||
214,5,65,0,0,214,215,5,83,0,0,215,216,5,83,0,0,216,74,1,0,0,0,217,
|
||||
218,5,44,0,0,218,76,1,0,0,0,219,220,7,0,0,0,220,78,1,0,0,0,221,223,
|
||||
3,77,38,0,222,221,1,0,0,0,223,224,1,0,0,0,224,222,1,0,0,0,224,225,
|
||||
1,0,0,0,225,232,1,0,0,0,226,228,5,46,0,0,227,229,3,77,38,0,228,227,
|
||||
1,0,0,0,229,230,1,0,0,0,230,228,1,0,0,0,230,231,1,0,0,0,231,233,
|
||||
1,0,0,0,232,226,1,0,0,0,232,233,1,0,0,0,233,80,1,0,0,0,234,235,5,
|
||||
62,0,0,235,82,1,0,0,0,236,237,5,42,0,0,237,84,1,0,0,0,238,239,5,
|
||||
116,0,0,239,86,1,0,0,0,240,241,7,1,0,0,241,88,1,0,0,0,242,243,7,
|
||||
2,0,0,243,90,1,0,0,0,244,245,5,73,0,0,245,246,5,79,0,0,246,247,5,
|
||||
80,0,0,247,92,1,0,0,0,248,250,5,13,0,0,249,248,1,0,0,0,249,250,1,
|
||||
0,0,0,250,251,1,0,0,0,251,252,5,10,0,0,252,94,1,0,0,0,253,255,7,
|
||||
3,0,0,254,253,1,0,0,0,255,256,1,0,0,0,256,254,1,0,0,0,256,257,1,
|
||||
0,0,0,257,258,1,0,0,0,258,259,6,47,0,0,259,96,1,0,0,0,260,261,5,
|
||||
47,0,0,261,262,5,47,0,0,262,266,1,0,0,0,263,265,8,4,0,0,264,263,
|
||||
1,0,0,0,265,268,1,0,0,0,266,264,1,0,0,0,266,267,1,0,0,0,267,277,
|
||||
1,0,0,0,268,266,1,0,0,0,269,273,5,35,0,0,270,272,8,4,0,0,271,270,
|
||||
1,0,0,0,272,275,1,0,0,0,273,271,1,0,0,0,273,274,1,0,0,0,274,277,
|
||||
1,0,0,0,275,273,1,0,0,0,276,260,1,0,0,0,276,269,1,0,0,0,277,278,
|
||||
1,0,0,0,278,279,6,48,0,0,279,98,1,0,0,0,9,0,224,230,232,249,256,
|
||||
266,273,276,1,6,0,0
|
||||
]
|
||||
|
||||
class CommentMacroLexer(Lexer):
|
||||
|
||||
atn = ATNDeserializer().deserialize(serializedATN())
|
||||
|
||||
decisionsToDFA = [ DFA(ds, i) for i, ds in enumerate(atn.decisionToState) ]
|
||||
|
||||
T__0 = 1
|
||||
T__1 = 2
|
||||
T__2 = 3
|
||||
T__3 = 4
|
||||
T__4 = 5
|
||||
T__5 = 6
|
||||
T__6 = 7
|
||||
T__7 = 8
|
||||
T__8 = 9
|
||||
T__9 = 10
|
||||
T__10 = 11
|
||||
T__11 = 12
|
||||
T__12 = 13
|
||||
T__13 = 14
|
||||
T__14 = 15
|
||||
T__15 = 16
|
||||
T__16 = 17
|
||||
T__17 = 18
|
||||
T__18 = 19
|
||||
T__19 = 20
|
||||
T__20 = 21
|
||||
T__21 = 22
|
||||
T__22 = 23
|
||||
T__23 = 24
|
||||
T__24 = 25
|
||||
T__25 = 26
|
||||
T__26 = 27
|
||||
T__27 = 28
|
||||
T__28 = 29
|
||||
T__29 = 30
|
||||
T__30 = 31
|
||||
T__31 = 32
|
||||
T__32 = 33
|
||||
T__33 = 34
|
||||
T__34 = 35
|
||||
T__35 = 36
|
||||
T__36 = 37
|
||||
T__37 = 38
|
||||
NUMBER = 39
|
||||
THRU = 40
|
||||
CURRENT = 41
|
||||
TIME = 42
|
||||
WHOLEHOG = 43
|
||||
DP8K = 44
|
||||
IOP = 45
|
||||
NEWLINE = 46
|
||||
WS = 47
|
||||
COMMENT = 48
|
||||
|
||||
channelNames = [ u"DEFAULT_TOKEN_CHANNEL", u"HIDDEN" ]
|
||||
|
||||
modeNames = [ "DEFAULT_MODE" ]
|
||||
|
||||
literalNames = [ "<INVALID>",
|
||||
"':'", "'GM'", "'/'", "'HM'", "'AM'", "'RM'", "'RA'", "'RO'",
|
||||
"'FM'", "'FGM'", "'CM'", "'GL'", "'HL'", "'AL'", "'RL'", "'GB'",
|
||||
"'HB'", "'AB'", "'RB'", "'GS'", "'HS'", "'AS'", "'RS'", "'CP'",
|
||||
"'+'", "'-'", "'RV'", "'RN'", "'GK'", "'HK'", "'RK'", "'INT'",
|
||||
"'POS'", "'COLR'", "'BEAM'", "'WAIT'", "'PASS'", "','", "'>'",
|
||||
"'*'", "'t'", "'IOP'" ]
|
||||
|
||||
symbolicNames = [ "<INVALID>",
|
||||
"NUMBER", "THRU", "CURRENT", "TIME", "WHOLEHOG", "DP8K", "IOP",
|
||||
"NEWLINE", "WS", "COMMENT" ]
|
||||
|
||||
ruleNames = [ "T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6",
|
||||
"T__7", "T__8", "T__9", "T__10", "T__11", "T__12", "T__13",
|
||||
"T__14", "T__15", "T__16", "T__17", "T__18", "T__19",
|
||||
"T__20", "T__21", "T__22", "T__23", "T__24", "T__25",
|
||||
"T__26", "T__27", "T__28", "T__29", "T__30", "T__31",
|
||||
"T__32", "T__33", "T__34", "T__35", "T__36", "T__37",
|
||||
"DIGIT", "NUMBER", "THRU", "CURRENT", "TIME", "WHOLEHOG",
|
||||
"DP8K", "IOP", "NEWLINE", "WS", "COMMENT" ]
|
||||
|
||||
grammarFileName = "CommentMacro.g4"
|
||||
|
||||
def __init__(self, input=None, output:TextIO = sys.stdout):
|
||||
super().__init__(input, output)
|
||||
self.checkVersion("4.10.1")
|
||||
self._interp = LexerATNSimulator(self, self.atn, self.decisionsToDFA, PredictionContextCache())
|
||||
self._actions = None
|
||||
self._predicates = None
|
||||
|
||||
|
|
@ -0,0 +1,417 @@
|
|||
# Generated from CommentMacro.g4 by ANTLR 4.10.1
|
||||
from antlr4 import *
|
||||
if __name__ is not None and "." in __name__:
|
||||
from .CommentMacroParser import CommentMacroParser
|
||||
else:
|
||||
from CommentMacroParser import CommentMacroParser
|
||||
|
||||
# This class defines a complete listener for a parse tree produced by CommentMacroParser.
|
||||
class CommentMacroListener(ParseTreeListener):
|
||||
|
||||
# Enter a parse tree produced by CommentMacroParser#prog.
|
||||
def enterProg(self, ctx:CommentMacroParser.ProgContext):
|
||||
pass
|
||||
|
||||
# Exit a parse tree produced by CommentMacroParser#prog.
|
||||
def exitProg(self, ctx:CommentMacroParser.ProgContext):
|
||||
pass
|
||||
|
||||
|
||||
# Enter a parse tree produced by CommentMacroParser#statement.
|
||||
def enterStatement(self, ctx:CommentMacroParser.StatementContext):
|
||||
pass
|
||||
|
||||
# Exit a parse tree produced by CommentMacroParser#statement.
|
||||
def exitStatement(self, ctx:CommentMacroParser.StatementContext):
|
||||
pass
|
||||
|
||||
|
||||
# Enter a parse tree produced by CommentMacroParser#MasterGo.
|
||||
def enterMasterGo(self, ctx:CommentMacroParser.MasterGoContext):
|
||||
pass
|
||||
|
||||
# Exit a parse tree produced by CommentMacroParser#MasterGo.
|
||||
def exitMasterGo(self, ctx:CommentMacroParser.MasterGoContext):
|
||||
pass
|
||||
|
||||
|
||||
# Enter a parse tree produced by CommentMacroParser#MasterGoto.
|
||||
def enterMasterGoto(self, ctx:CommentMacroParser.MasterGotoContext):
|
||||
pass
|
||||
|
||||
# Exit a parse tree produced by CommentMacroParser#MasterGoto.
|
||||
def exitMasterGoto(self, ctx:CommentMacroParser.MasterGotoContext):
|
||||
pass
|
||||
|
||||
|
||||
# Enter a parse tree produced by CommentMacroParser#MasterHalt.
|
||||
def enterMasterHalt(self, ctx:CommentMacroParser.MasterHaltContext):
|
||||
pass
|
||||
|
||||
# Exit a parse tree produced by CommentMacroParser#MasterHalt.
|
||||
def exitMasterHalt(self, ctx:CommentMacroParser.MasterHaltContext):
|
||||
pass
|
||||
|
||||
|
||||
# Enter a parse tree produced by CommentMacroParser#MasterAssert.
|
||||
def enterMasterAssert(self, ctx:CommentMacroParser.MasterAssertContext):
|
||||
pass
|
||||
|
||||
# Exit a parse tree produced by CommentMacroParser#MasterAssert.
|
||||
def exitMasterAssert(self, ctx:CommentMacroParser.MasterAssertContext):
|
||||
pass
|
||||
|
||||
|
||||
# Enter a parse tree produced by CommentMacroParser#MasterRelease.
|
||||
def enterMasterRelease(self, ctx:CommentMacroParser.MasterReleaseContext):
|
||||
pass
|
||||
|
||||
# Exit a parse tree produced by CommentMacroParser#MasterRelease.
|
||||
def exitMasterRelease(self, ctx:CommentMacroParser.MasterReleaseContext):
|
||||
pass
|
||||
|
||||
|
||||
# Enter a parse tree produced by CommentMacroParser#ReleaseAll.
|
||||
def enterReleaseAll(self, ctx:CommentMacroParser.ReleaseAllContext):
|
||||
pass
|
||||
|
||||
# Exit a parse tree produced by CommentMacroParser#ReleaseAll.
|
||||
def exitReleaseAll(self, ctx:CommentMacroParser.ReleaseAllContext):
|
||||
pass
|
||||
|
||||
|
||||
# Enter a parse tree produced by CommentMacroParser#ReleaseOthers.
|
||||
def enterReleaseOthers(self, ctx:CommentMacroParser.ReleaseOthersContext):
|
||||
pass
|
||||
|
||||
# Exit a parse tree produced by CommentMacroParser#ReleaseOthers.
|
||||
def exitReleaseOthers(self, ctx:CommentMacroParser.ReleaseOthersContext):
|
||||
pass
|
||||
|
||||
|
||||
# Enter a parse tree produced by CommentMacroParser#MasterFade.
|
||||
def enterMasterFade(self, ctx:CommentMacroParser.MasterFadeContext):
|
||||
pass
|
||||
|
||||
# Exit a parse tree produced by CommentMacroParser#MasterFade.
|
||||
def exitMasterFade(self, ctx:CommentMacroParser.MasterFadeContext):
|
||||
pass
|
||||
|
||||
|
||||
# Enter a parse tree produced by CommentMacroParser#FadeGrandMaster.
|
||||
def enterFadeGrandMaster(self, ctx:CommentMacroParser.FadeGrandMasterContext):
|
||||
pass
|
||||
|
||||
# Exit a parse tree produced by CommentMacroParser#FadeGrandMaster.
|
||||
def exitFadeGrandMaster(self, ctx:CommentMacroParser.FadeGrandMasterContext):
|
||||
pass
|
||||
|
||||
|
||||
# Enter a parse tree produced by CommentMacroParser#MasterChoose.
|
||||
def enterMasterChoose(self, ctx:CommentMacroParser.MasterChooseContext):
|
||||
pass
|
||||
|
||||
# Exit a parse tree produced by CommentMacroParser#MasterChoose.
|
||||
def exitMasterChoose(self, ctx:CommentMacroParser.MasterChooseContext):
|
||||
pass
|
||||
|
||||
|
||||
# Enter a parse tree produced by CommentMacroParser#ListGo.
|
||||
def enterListGo(self, ctx:CommentMacroParser.ListGoContext):
|
||||
pass
|
||||
|
||||
# Exit a parse tree produced by CommentMacroParser#ListGo.
|
||||
def exitListGo(self, ctx:CommentMacroParser.ListGoContext):
|
||||
pass
|
||||
|
||||
|
||||
# Enter a parse tree produced by CommentMacroParser#ListGoto.
|
||||
def enterListGoto(self, ctx:CommentMacroParser.ListGotoContext):
|
||||
pass
|
||||
|
||||
# Exit a parse tree produced by CommentMacroParser#ListGoto.
|
||||
def exitListGoto(self, ctx:CommentMacroParser.ListGotoContext):
|
||||
pass
|
||||
|
||||
|
||||
# Enter a parse tree produced by CommentMacroParser#ListHalt.
|
||||
def enterListHalt(self, ctx:CommentMacroParser.ListHaltContext):
|
||||
pass
|
||||
|
||||
# Exit a parse tree produced by CommentMacroParser#ListHalt.
|
||||
def exitListHalt(self, ctx:CommentMacroParser.ListHaltContext):
|
||||
pass
|
||||
|
||||
|
||||
# Enter a parse tree produced by CommentMacroParser#ListAssert.
|
||||
def enterListAssert(self, ctx:CommentMacroParser.ListAssertContext):
|
||||
pass
|
||||
|
||||
# Exit a parse tree produced by CommentMacroParser#ListAssert.
|
||||
def exitListAssert(self, ctx:CommentMacroParser.ListAssertContext):
|
||||
pass
|
||||
|
||||
|
||||
# Enter a parse tree produced by CommentMacroParser#ListRelese.
|
||||
def enterListRelese(self, ctx:CommentMacroParser.ListReleseContext):
|
||||
pass
|
||||
|
||||
# Exit a parse tree produced by CommentMacroParser#ListRelese.
|
||||
def exitListRelese(self, ctx:CommentMacroParser.ListReleseContext):
|
||||
pass
|
||||
|
||||
|
||||
# Enter a parse tree produced by CommentMacroParser#BatchGo.
|
||||
def enterBatchGo(self, ctx:CommentMacroParser.BatchGoContext):
|
||||
pass
|
||||
|
||||
# Exit a parse tree produced by CommentMacroParser#BatchGo.
|
||||
def exitBatchGo(self, ctx:CommentMacroParser.BatchGoContext):
|
||||
pass
|
||||
|
||||
|
||||
# Enter a parse tree produced by CommentMacroParser#BatchHalt.
|
||||
def enterBatchHalt(self, ctx:CommentMacroParser.BatchHaltContext):
|
||||
pass
|
||||
|
||||
# Exit a parse tree produced by CommentMacroParser#BatchHalt.
|
||||
def exitBatchHalt(self, ctx:CommentMacroParser.BatchHaltContext):
|
||||
pass
|
||||
|
||||
|
||||
# Enter a parse tree produced by CommentMacroParser#BatchAssert.
|
||||
def enterBatchAssert(self, ctx:CommentMacroParser.BatchAssertContext):
|
||||
pass
|
||||
|
||||
# Exit a parse tree produced by CommentMacroParser#BatchAssert.
|
||||
def exitBatchAssert(self, ctx:CommentMacroParser.BatchAssertContext):
|
||||
pass
|
||||
|
||||
|
||||
# Enter a parse tree produced by CommentMacroParser#BatchRelease.
|
||||
def enterBatchRelease(self, ctx:CommentMacroParser.BatchReleaseContext):
|
||||
pass
|
||||
|
||||
# Exit a parse tree produced by CommentMacroParser#BatchRelease.
|
||||
def exitBatchRelease(self, ctx:CommentMacroParser.BatchReleaseContext):
|
||||
pass
|
||||
|
||||
|
||||
# Enter a parse tree produced by CommentMacroParser#SceneGo.
|
||||
def enterSceneGo(self, ctx:CommentMacroParser.SceneGoContext):
|
||||
pass
|
||||
|
||||
# Exit a parse tree produced by CommentMacroParser#SceneGo.
|
||||
def exitSceneGo(self, ctx:CommentMacroParser.SceneGoContext):
|
||||
pass
|
||||
|
||||
|
||||
# Enter a parse tree produced by CommentMacroParser#SceneHalt.
|
||||
def enterSceneHalt(self, ctx:CommentMacroParser.SceneHaltContext):
|
||||
pass
|
||||
|
||||
# Exit a parse tree produced by CommentMacroParser#SceneHalt.
|
||||
def exitSceneHalt(self, ctx:CommentMacroParser.SceneHaltContext):
|
||||
pass
|
||||
|
||||
|
||||
# Enter a parse tree produced by CommentMacroParser#SceneAssert.
|
||||
def enterSceneAssert(self, ctx:CommentMacroParser.SceneAssertContext):
|
||||
pass
|
||||
|
||||
# Exit a parse tree produced by CommentMacroParser#SceneAssert.
|
||||
def exitSceneAssert(self, ctx:CommentMacroParser.SceneAssertContext):
|
||||
pass
|
||||
|
||||
|
||||
# Enter a parse tree produced by CommentMacroParser#SceneRelease.
|
||||
def enterSceneRelease(self, ctx:CommentMacroParser.SceneReleaseContext):
|
||||
pass
|
||||
|
||||
# Exit a parse tree produced by CommentMacroParser#SceneRelease.
|
||||
def exitSceneRelease(self, ctx:CommentMacroParser.SceneReleaseContext):
|
||||
pass
|
||||
|
||||
|
||||
# Enter a parse tree produced by CommentMacroParser#PageChange.
|
||||
def enterPageChange(self, ctx:CommentMacroParser.PageChangeContext):
|
||||
pass
|
||||
|
||||
# Exit a parse tree produced by CommentMacroParser#PageChange.
|
||||
def exitPageChange(self, ctx:CommentMacroParser.PageChangeContext):
|
||||
pass
|
||||
|
||||
|
||||
# Enter a parse tree produced by CommentMacroParser#PageNext.
|
||||
def enterPageNext(self, ctx:CommentMacroParser.PageNextContext):
|
||||
pass
|
||||
|
||||
# Exit a parse tree produced by CommentMacroParser#PageNext.
|
||||
def exitPageNext(self, ctx:CommentMacroParser.PageNextContext):
|
||||
pass
|
||||
|
||||
|
||||
# Enter a parse tree produced by CommentMacroParser#PagePrev.
|
||||
def enterPagePrev(self, ctx:CommentMacroParser.PagePrevContext):
|
||||
pass
|
||||
|
||||
# Exit a parse tree produced by CommentMacroParser#PagePrev.
|
||||
def exitPagePrev(self, ctx:CommentMacroParser.PagePrevContext):
|
||||
pass
|
||||
|
||||
|
||||
# Enter a parse tree produced by CommentMacroParser#RecallView.
|
||||
def enterRecallView(self, ctx:CommentMacroParser.RecallViewContext):
|
||||
pass
|
||||
|
||||
# Exit a parse tree produced by CommentMacroParser#RecallView.
|
||||
def exitRecallView(self, ctx:CommentMacroParser.RecallViewContext):
|
||||
pass
|
||||
|
||||
|
||||
# Enter a parse tree produced by CommentMacroParser#NodeReset.
|
||||
def enterNodeReset(self, ctx:CommentMacroParser.NodeResetContext):
|
||||
pass
|
||||
|
||||
# Exit a parse tree produced by CommentMacroParser#NodeReset.
|
||||
def exitNodeReset(self, ctx:CommentMacroParser.NodeResetContext):
|
||||
pass
|
||||
|
||||
|
||||
# Enter a parse tree produced by CommentMacroParser#MacroGo.
|
||||
def enterMacroGo(self, ctx:CommentMacroParser.MacroGoContext):
|
||||
pass
|
||||
|
||||
# Exit a parse tree produced by CommentMacroParser#MacroGo.
|
||||
def exitMacroGo(self, ctx:CommentMacroParser.MacroGoContext):
|
||||
pass
|
||||
|
||||
|
||||
# Enter a parse tree produced by CommentMacroParser#MacroHalt.
|
||||
def enterMacroHalt(self, ctx:CommentMacroParser.MacroHaltContext):
|
||||
pass
|
||||
|
||||
# Exit a parse tree produced by CommentMacroParser#MacroHalt.
|
||||
def exitMacroHalt(self, ctx:CommentMacroParser.MacroHaltContext):
|
||||
pass
|
||||
|
||||
|
||||
# Enter a parse tree produced by CommentMacroParser#MacroStop.
|
||||
def enterMacroStop(self, ctx:CommentMacroParser.MacroStopContext):
|
||||
pass
|
||||
|
||||
# Exit a parse tree produced by CommentMacroParser#MacroStop.
|
||||
def exitMacroStop(self, ctx:CommentMacroParser.MacroStopContext):
|
||||
pass
|
||||
|
||||
|
||||
# Enter a parse tree produced by CommentMacroParser#SelectIntensity.
|
||||
def enterSelectIntensity(self, ctx:CommentMacroParser.SelectIntensityContext):
|
||||
pass
|
||||
|
||||
# Exit a parse tree produced by CommentMacroParser#SelectIntensity.
|
||||
def exitSelectIntensity(self, ctx:CommentMacroParser.SelectIntensityContext):
|
||||
pass
|
||||
|
||||
|
||||
# Enter a parse tree produced by CommentMacroParser#SelectPosition.
|
||||
def enterSelectPosition(self, ctx:CommentMacroParser.SelectPositionContext):
|
||||
pass
|
||||
|
||||
# Exit a parse tree produced by CommentMacroParser#SelectPosition.
|
||||
def exitSelectPosition(self, ctx:CommentMacroParser.SelectPositionContext):
|
||||
pass
|
||||
|
||||
|
||||
# Enter a parse tree produced by CommentMacroParser#SelectColour.
|
||||
def enterSelectColour(self, ctx:CommentMacroParser.SelectColourContext):
|
||||
pass
|
||||
|
||||
# Exit a parse tree produced by CommentMacroParser#SelectColour.
|
||||
def exitSelectColour(self, ctx:CommentMacroParser.SelectColourContext):
|
||||
pass
|
||||
|
||||
|
||||
# Enter a parse tree produced by CommentMacroParser#SelectBeam.
|
||||
def enterSelectBeam(self, ctx:CommentMacroParser.SelectBeamContext):
|
||||
pass
|
||||
|
||||
# Exit a parse tree produced by CommentMacroParser#SelectBeam.
|
||||
def exitSelectBeam(self, ctx:CommentMacroParser.SelectBeamContext):
|
||||
pass
|
||||
|
||||
|
||||
# Enter a parse tree produced by CommentMacroParser#Wait.
|
||||
def enterWait(self, ctx:CommentMacroParser.WaitContext):
|
||||
pass
|
||||
|
||||
# Exit a parse tree produced by CommentMacroParser#Wait.
|
||||
def exitWait(self, ctx:CommentMacroParser.WaitContext):
|
||||
pass
|
||||
|
||||
|
||||
# Enter a parse tree produced by CommentMacroParser#Pass.
|
||||
def enterPass(self, ctx:CommentMacroParser.PassContext):
|
||||
pass
|
||||
|
||||
# Exit a parse tree produced by CommentMacroParser#Pass.
|
||||
def exitPass(self, ctx:CommentMacroParser.PassContext):
|
||||
pass
|
||||
|
||||
|
||||
# Enter a parse tree produced by CommentMacroParser#time.
|
||||
def enterTime(self, ctx:CommentMacroParser.TimeContext):
|
||||
pass
|
||||
|
||||
# Exit a parse tree produced by CommentMacroParser#time.
|
||||
def exitTime(self, ctx:CommentMacroParser.TimeContext):
|
||||
pass
|
||||
|
||||
|
||||
# Enter a parse tree produced by CommentMacroParser#device.
|
||||
def enterDevice(self, ctx:CommentMacroParser.DeviceContext):
|
||||
pass
|
||||
|
||||
# Exit a parse tree produced by CommentMacroParser#device.
|
||||
def exitDevice(self, ctx:CommentMacroParser.DeviceContext):
|
||||
pass
|
||||
|
||||
|
||||
# Enter a parse tree produced by CommentMacroParser#nodeType.
|
||||
def enterNodeType(self, ctx:CommentMacroParser.NodeTypeContext):
|
||||
pass
|
||||
|
||||
# Exit a parse tree produced by CommentMacroParser#nodeType.
|
||||
def exitNodeType(self, ctx:CommentMacroParser.NodeTypeContext):
|
||||
pass
|
||||
|
||||
|
||||
# Enter a parse tree produced by CommentMacroParser#target.
|
||||
def enterTarget(self, ctx:CommentMacroParser.TargetContext):
|
||||
pass
|
||||
|
||||
# Exit a parse tree produced by CommentMacroParser#target.
|
||||
def exitTarget(self, ctx:CommentMacroParser.TargetContext):
|
||||
pass
|
||||
|
||||
|
||||
# Enter a parse tree produced by CommentMacroParser#span.
|
||||
def enterSpan(self, ctx:CommentMacroParser.SpanContext):
|
||||
pass
|
||||
|
||||
# Exit a parse tree produced by CommentMacroParser#span.
|
||||
def exitSpan(self, ctx:CommentMacroParser.SpanContext):
|
||||
pass
|
||||
|
||||
|
||||
# Enter a parse tree produced by CommentMacroParser#number.
|
||||
def enterNumber(self, ctx:CommentMacroParser.NumberContext):
|
||||
pass
|
||||
|
||||
# Exit a parse tree produced by CommentMacroParser#number.
|
||||
def exitNumber(self, ctx:CommentMacroParser.NumberContext):
|
||||
pass
|
||||
|
||||
|
||||
|
||||
del CommentMacroParser
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1 @@
|
|||
"""Init for comment macro antlr4."""
|
|
@ -0,0 +1,121 @@
|
|||
"""hog4.py: Class methods for Hog 4 representation."""
|
||||
|
||||
import logging
|
||||
from time import sleep
|
||||
from typing import Any, Dict, Union
|
||||
from pythonosc import udp_client, osc_message_builder, osc_bundle, osc_message
|
||||
from antlr4 import ParserRuleContext
|
||||
|
||||
__all__ = [
|
||||
"HogNet",
|
||||
]
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
class HogNet:
|
||||
"""Class definition of a hognet participant."""
|
||||
|
||||
# button state constants
|
||||
buttonDOWN = 1
|
||||
buttonUP = 0
|
||||
buttonMap: Dict[str, str] = {
|
||||
"backspace": "/hog/hardware/backspace",
|
||||
"beam": "/hog/hardware/beam",
|
||||
"blind": "/hog/hardware/blind",
|
||||
"clear": "/hog/hardware/clear",
|
||||
"colour": "/hog/hardware/colour",
|
||||
"copy": "/hog/hardware/copy",
|
||||
"cue": "/hog/hardware/cue",
|
||||
"delete": "/hog/hardware/delete",
|
||||
"down": "/hog/hardware/down",
|
||||
"effect": "/hog/hardware/effect",
|
||||
"enter": "/hog/hardware/enter",
|
||||
"fan": "/hog/hardware/fan",
|
||||
"fixture": "/hog/hardware/fixture",
|
||||
"goto": "/hog/hardware/goto",
|
||||
"group": "/hog/hardware/group",
|
||||
"highlight": "/hog/hardware/highlight",
|
||||
"intensity": "/hog/hardware/intensity",
|
||||
"left": "/hog/hardware/left",
|
||||
"list": "/hog/hardware/list",
|
||||
"live": "/hog/hardware/live",
|
||||
"macro": "/hog/hardware/macro",
|
||||
"merge": "/hog/hardware/merge",
|
||||
"move": "/hog/hardware/move",
|
||||
"open": "/hog/hardware/open",
|
||||
"page": "/hog/hardware/page",
|
||||
"pig": "/hog/hardware/pig",
|
||||
"position": "/hog/hardware/position",
|
||||
"record": "/hog/hardware/record",
|
||||
"right": "/hog/hardware/right",
|
||||
"scene": "/hog/hardware/scene",
|
||||
"set": "/hog/hardware/set",
|
||||
"setup": "/hog/hardware/setup",
|
||||
"time": "/hog/hardware/time",
|
||||
"up": "/hog/hardware/up",
|
||||
"update": "/hog/hardware/update",
|
||||
".": "/hog/hardware/period",
|
||||
"@": "/hog/hardware/at",
|
||||
"-": "/hog/hardware/minus",
|
||||
"+": "/hog/hardware/plus",
|
||||
"/": "/hog/hardware/slash",
|
||||
"0": "/hog/hardware/zero",
|
||||
"1": "/hog/hardware/one",
|
||||
"2": "/hog/hardware/two",
|
||||
"3": "/hog/hardware/three",
|
||||
"4": "/hog/hardware/four",
|
||||
"5": "/hog/hardware/five",
|
||||
"6": "/hog/hardware/six",
|
||||
"7": "/hog/hardware/seven",
|
||||
"8": "/hog/hardware/eight",
|
||||
"9": "/hog/hardware/nine"
|
||||
}
|
||||
|
||||
def __init__(self, servers: Dict[int, object]) -> None:
|
||||
"""Init method."""
|
||||
self.servers = servers
|
||||
|
||||
def number_entry(self, device: ParserRuleContext,
|
||||
number: str) -> None:
|
||||
"""Press digit buttons to make a number."""
|
||||
for digit in number:
|
||||
try:
|
||||
self.button_press(device, self.buttonMap[digit])
|
||||
except KeyError:
|
||||
continue
|
||||
|
||||
def button_press(self, device: ParserRuleContext,
|
||||
path: str, delay: float = 0.05) -> None:
|
||||
"""Button presses are a pair of up/down OSC."""
|
||||
self.send_message(device, path, self.buttonDOWN)
|
||||
sleep(delay)
|
||||
self.send_message(device, path, self.buttonUP)
|
||||
sleep(delay)
|
||||
|
||||
def send_message(self, device: ParserRuleContext,
|
||||
path: str, arg: Any) -> None:
|
||||
"""Send a simple OSC message with one argument."""
|
||||
msg = osc_message_builder.OscMessageBuilder(address=path)
|
||||
msg.add_arg(arg)
|
||||
self.send(device, msg.build())
|
||||
|
||||
def send(self, device: ParserRuleContext,
|
||||
msg: Union[osc_message.OscMessage, osc_bundle.OscBundle]) -> None:
|
||||
"""Send python-osc messages."""
|
||||
if device is None:
|
||||
# first configured server
|
||||
osc: udp_client = list(self.servers.values())[0]
|
||||
else:
|
||||
if device.nodeType().getText().lower() != 'h':
|
||||
log.error("ERROR: Only Hog type devices are supported.")
|
||||
return
|
||||
try:
|
||||
osc = self.servers[device.number().value]
|
||||
except KeyError:
|
||||
log.error("ERROR: Net# %d not found.",
|
||||
device.number().value)
|
||||
return
|
||||
try:
|
||||
osc.send(msg)
|
||||
except OSError as exception:
|
||||
log.error(exception)
|
|
@ -0,0 +1,84 @@
|
|||
"""comment.py: Hog 4 comment macro interpreter and OSC bridge."""
|
||||
|
||||
import configparser
|
||||
import logging
|
||||
from typing import Dict
|
||||
|
||||
from antlr4 import CommonTokenStream, InputStream, ParseTreeWalker
|
||||
from antlr4.error.ErrorListener import ErrorListener
|
||||
from pythonosc import udp_client
|
||||
|
||||
from .commentmacro.CommentMacroLexer import CommentMacroLexer
|
||||
from .commentmacro.CommentMacroParser import CommentMacroParser
|
||||
from .OscListener import OscCommentMacroListener
|
||||
|
||||
__all__ = [
|
||||
"SyntaxErrorListener",
|
||||
"load_servers",
|
||||
"comment",
|
||||
"WALKER",
|
||||
"LISTENER",
|
||||
]
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
class SyntaxErrorListener(ErrorListener):
|
||||
"""An error listener that raises SyntaxError exceptions."""
|
||||
|
||||
def syntaxError(self, recognizer, offendingSymbol, line, column, msg, e):
|
||||
raise SyntaxError(f"line {line}:{column} {msg}")
|
||||
|
||||
|
||||
def load_servers(file: str = 'server.cfg') -> Dict[int, object]:
|
||||
"""Load an ini style configuration file."""
|
||||
# empty server dictionary
|
||||
servers: Dict[int, object] = {}
|
||||
|
||||
# open config file
|
||||
config = configparser.ConfigParser(allow_no_value=True)
|
||||
config.read(file)
|
||||
|
||||
# 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
|
||||
addr = server.get("ip", fallback="127.0.0.1")
|
||||
port = server.getint("port", fallback=7001)
|
||||
net = server.getint("net", fallback=1)
|
||||
# osc clients are added to the dictionary with the net # as the key
|
||||
log.info("Adding Hog device at net# %s", net)
|
||||
servers[net] = udp_client.SimpleUDPClient(addr, port)
|
||||
except KeyError as exception:
|
||||
log.error('Error configuring net#%s: %s', net, exception)
|
||||
continue
|
||||
return servers
|
||||
|
||||
|
||||
# init reusable walker and listener
|
||||
WALKER: ParseTreeWalker = ParseTreeWalker()
|
||||
LISTENER: OscCommentMacroListener = OscCommentMacroListener()
|
||||
|
||||
|
||||
def comment(text: str) -> None:
|
||||
"""Process comment macro input."""
|
||||
# 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 exception:
|
||||
log.debug(exception)
|
|
@ -0,0 +1,34 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""Interactive BaconScript shell."""
|
||||
|
||||
import logging
|
||||
import sys
|
||||
from .bacon import comment, LISTENER, HogNet, load_servers
|
||||
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
LISTENER.osc = HogNet(load_servers('server.cfg'))
|
||||
|
||||
# handle user input if run directly
|
||||
if __name__ == '__main__':
|
||||
if len(sys.argv) > 1:
|
||||
# look for macros passed as arguments
|
||||
logging.debug("found macro at argv[1]")
|
||||
comment(sys.argv[1])
|
||||
else:
|
||||
# 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)
|
74
comment.py
74
comment.py
|
@ -1,74 +0,0 @@
|
|||
#!/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 antlr4
|
||||
import configparser
|
||||
import logging
|
||||
import sys
|
||||
|
||||
from CommentMacroLexer import CommentMacroLexer
|
||||
from CommentMacroParser import CommentMacroParser
|
||||
from OscCommentMacroListener import OscCommentMacroListener
|
||||
from pythonosc import udp_client
|
||||
|
||||
|
||||
# setup logging
|
||||
logger = logging.getLogger("CommentMacro")
|
||||
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
|
||||
|
||||
# TODO: refactor this to support multiple net#s
|
||||
config = configparser.ConfigParser(allow_no_value=True)
|
||||
config.read('server.cfg') # open config file
|
||||
servers = {} # init an empty dictionary
|
||||
server = config['hog4'] # section of config file
|
||||
net = server.getint("net", 1) # default to net #1
|
||||
logger.info("Adding Hog device at net# " + str(net))
|
||||
# osc clients are added to the dictionary with the net # as the key
|
||||
servers[net] = udp_client.SimpleUDPClient(server.get("ip", "10.0.0.1"),
|
||||
server.getint("port", 6600))
|
||||
|
||||
|
||||
def comment(text):
|
||||
input_stream = antlr4.InputStream(text)
|
||||
lexer = CommentMacroLexer(input_stream)
|
||||
stream = antlr4.CommonTokenStream(lexer)
|
||||
parser = CommentMacroParser(stream)
|
||||
tree = parser.prog()
|
||||
oscMacro = OscCommentMacroListener(servers)
|
||||
walker = antlr4.ParseTreeWalker()
|
||||
walker.walk(oscMacro, tree)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if len(sys.argv) > 1:
|
||||
logger.debug("found macro at argv[1]")
|
||||
comment(sys.argv[1])
|
||||
else:
|
||||
import readline # for input history and line editing
|
||||
while True:
|
||||
try:
|
||||
text = input("comment# ")
|
||||
except KeyboardInterrupt:
|
||||
text = 'exit'
|
||||
print(text)
|
||||
if text == 'exit':
|
||||
sys.exit(0)
|
||||
else:
|
||||
comment(text)
|
|
@ -0,0 +1,13 @@
|
|||
// example.bs: An example BaconScript file.
|
||||
CM10
|
||||
GM*
|
||||
GM1:AM*:HM3 # use a `:` to separate multiple macros on a single line.
|
||||
RM*
|
||||
WAIT1 # sleep for 1 second
|
||||
RA
|
||||
FM1/50
|
||||
FGM20
|
||||
GL1/5
|
||||
HS3>5 # do macro on a range of targets
|
||||
RK2,4,6 # do macro on a comma separated list of targets
|
||||
CP+
|
30
server.cfg
30
server.cfg
|
@ -1,4 +1,28 @@
|
|||
; This file contains the configuration data for HogNet devices.
|
||||
|
||||
[network]
|
||||
; Comma seperated list of config section names.
|
||||
; The first Hog4 in the list will be the default OSC reciever.
|
||||
hogs = hog4,hedgehog
|
||||
|
||||
|
||||
; The device is named as a section.
|
||||
; When adding additional devices, be sure to add the section
|
||||
; name to the index on line 6.
|
||||
[example]
|
||||
; the IPv4 or IPv6 address of the Hog device
|
||||
ip: 127.0.0.1
|
||||
; the port which is configured for OSC input
|
||||
port: 7001
|
||||
; the net number, which may be called in the comment macro
|
||||
net: 1
|
||||
|
||||
[hog4]
|
||||
ip: 10.0.0.100
|
||||
port: 7001
|
||||
net: 1
|
||||
ip: 10.235.1.53
|
||||
port: 7001
|
||||
net: 53
|
||||
|
||||
[hedgehog]
|
||||
ip: 10.235.1.63
|
||||
port: 7001
|
||||
net: 63
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
; This file contains the configuration data for HogNet devices.
|
||||
|
||||
[network]
|
||||
; Comma seperated list of config section names.
|
||||
; The first Hog4 in the list will be the default OSC reciever.
|
||||
hogs = hog4,hedgehog
|
||||
|
||||
|
||||
; The device is named as a section.
|
||||
; When adding additional devices, be sure to add the section
|
||||
; name to the index on line 6.
|
||||
[example]
|
||||
; the IPv4 or IPv6 address of the Hog device
|
||||
ip: 127.0.0.1
|
||||
; the port which is configured for OSC input
|
||||
port: 7001
|
||||
; the net number, which may be called in the comment macro
|
||||
net: 1
|
||||
|
||||
[hog4]
|
||||
ip: 10.235.1.53
|
||||
port: 7001
|
||||
net: 53
|
||||
|
||||
[hedgehog]
|
||||
ip: 10.235.1.63
|
||||
port: 7001
|
||||
net: 63
|
|
@ -0,0 +1,20 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""Setup.py: Module install script."""
|
||||
|
||||
from setuptools import setup, find_packages
|
||||
|
||||
setup(name='baconscript',
|
||||
version='3.9',
|
||||
description='Hog 4 comment macro interpreter and OSC bridge.',
|
||||
url='https://git.company235.com/kevin/baconscript',
|
||||
author='Kevin Matz',
|
||||
author_email='kevin@company235.com',
|
||||
license='MIT',
|
||||
packages=find_packages(),
|
||||
install_requires=[
|
||||
'antlr4-python3-runtime',
|
||||
'python-osc',
|
||||
],
|
||||
zip_safe=False)
|
Loading…
Reference in New Issue