Compare commits
97 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 | |
Kevin Matz | 1c4c4b18a2 | |
Kevin Matz | 54340773bc | |
Kevin Matz | 01e8a09925 | |
Kevin Matz | ffed6d35e3 | |
Kevin Matz | 10d30ae5e7 | |
Kevin Matz | f284414383 | |
Kevin Matz | 999624bd49 | |
Kevin Matz | 1aaf12b6f3 | |
Kevin Matz | ee08529059 | |
Kevin Matz | 48d8c3ec4f | |
Kevin Matz | 19c2a4ef55 | |
Kevin Matz | 6eb8b35aea | |
Kevin Matz | 5014f71915 | |
Kevin Matz | 2a42b496ef | |
Kevin Matz | 6ab15f8dbe | |
Kevin Matz | e94e89be85 | |
Kevin Matz | dec487298e | |
Kevin Matz | f96da2939c | |
Kevin Matz | 5f808f4cf6 | |
Kevin Matz | 345c51e6ca | |
Kevin Matz | d3c497c837 | |
Kevin Matz | 88f7b825a8 | |
Kevin Matz | 7c54d9fb1e | |
Kevin Matz | 31eb6a2af8 | |
Kevin Matz | 1d7612e57c | |
Kevin Matz | 3eab5b9626 |
|
@ -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' number (device)? // Go Keystroke Macro
|
||||
| 'HK' number (device)? // Halt Keystroke Macro
|
||||
| 'RK' number (device)? // Stop Keystroke Macro
|
||||
;
|
||||
|
||||
master : (target | CURRENT) ;
|
||||
time : TIME number ;
|
||||
device : nodeType number ;
|
||||
|
||||
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,124 +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
|
||||
from CommentMacroParser import CommentMacroParser
|
||||
from CommentMacroListener import CommentMacroListener
|
||||
from OscMacroDefinitions import HogDevice
|
||||
|
||||
logger = logging.getLogger("CommentMacro")
|
||||
|
||||
|
||||
def num(string):
|
||||
try:
|
||||
num = int(string)
|
||||
return num
|
||||
except ValueError:
|
||||
num = float(string)
|
||||
return num
|
||||
|
||||
|
||||
# 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 = HogDevice(servers)
|
||||
|
||||
def exitDevice(self, ctx: CommentMacroParser.DeviceContext):
|
||||
if isinstance(ctx.parentCtx, CommentMacroParser.MacroContext):
|
||||
ctx.parentCtx.device = ctx
|
||||
|
||||
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))
|
||||
|
||||
# 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.")
|
||||
return -1
|
||||
logger.debug("Exiting Macro")
|
||||
|
||||
def enterMaster(self, ctx: CommentMacroParser.MasterContext):
|
||||
ctx.targets = []
|
||||
|
||||
def exitMaster(self, ctx: CommentMacroParser.MasterContext):
|
||||
ctx.targets = set(ctx.targets) # no duplicates
|
||||
if isinstance(ctx.parentCtx, CommentMacroParser.MacroContext):
|
||||
ctx.parentCtx.master = ctx
|
||||
|
||||
def exitNumber(self, ctx: CommentMacroParser.NumberContext):
|
||||
ctx.value = num(ctx.getText())
|
||||
if isinstance(ctx.parentCtx, CommentMacroParser.TargetContext):
|
||||
ctx.parentCtx.targets.append(ctx.value)
|
||||
if isinstance(ctx.parentCtx, CommentMacroParser.MacroContext):
|
||||
ctx.parentCtx.number = ctx
|
||||
if isinstance(ctx.parentCtx, CommentMacroParser.DeviceContext):
|
||||
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)):
|
||||
if isinstance(ctx.parentCtx, CommentMacroParser.TargetContext):
|
||||
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.")
|
||||
ctx.parentCtx.targets.append(-1)
|
||||
|
||||
def enterTarget(self, ctx: CommentMacroParser.TargetContext):
|
||||
ctx.targets = []
|
||||
|
||||
def exitTarget(self, ctx: CommentMacroParser.TargetContext):
|
||||
ctx.target = set(ctx.targets) # no duplicates
|
||||
ctx.parentCtx.targets.extend(ctx.targets) # add to parent targets
|
||||
|
||||
def exitNodeType(self, ctx: CommentMacroParser.NodeTypeContext):
|
||||
if isinstance(ctx.parentCtx, CommentMacroParser.DeviceContext):
|
||||
ctx.parentCtx.type = ctx
|
|
@ -1,188 +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():
|
||||
def __init__(self, servers):
|
||||
self.servers = servers
|
||||
|
||||
def button_press(self, device, path, delay=0.05):
|
||||
self.send_message(device, path, 1) # button down
|
||||
sleep(delay)
|
||||
self.send_message(device, path, 0) # 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.getText() != 'h'):
|
||||
logger.warn("Only Hog type devices are curently supported.")
|
||||
logger.error("ERROR: macro discarded!")
|
||||
return
|
||||
else:
|
||||
try:
|
||||
osc = self.servers[device.number.value]
|
||||
except KeyError:
|
||||
logger.warn("Net# "+str(device.number.value)+" not found.")
|
||||
logger.error("ERROR: macro discarded!")
|
||||
return
|
||||
osc.send(msg)
|
||||
|
||||
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.error("GO MASTER macro targets must be intigers. "
|
||||
+ str(i) + " is not an intigers.")
|
||||
continue
|
||||
if (i < 0):
|
||||
logger.error("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.error("GO MASTER macro targets must be intigers. "
|
||||
+ str(i) + " is not an intigers.")
|
||||
continue
|
||||
if (i < 0):
|
||||
logger.error("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_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.error("FADE MASTER macro targets must be intigers. "
|
||||
+ str(i) + " is not an intigers.")
|
||||
continue
|
||||
if (i < 0):
|
||||
logger.error("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 _list_go(self, ctx):
|
||||
for i in ctx.targets:
|
||||
list = str(i)
|
||||
if ctx.number is not None:
|
||||
list += "." + str(ctx.number.value)
|
||||
logger.info("Go on List " + 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)
|
||||
|
||||
command = {"GM": _master_go,
|
||||
"HM": _master_halt,
|
||||
"FM": _master_fade,
|
||||
"FGM": _master_fade_grand,
|
||||
"CM": _master_choose,
|
||||
"GL": _list_go,
|
||||
"HL": _list_halt,
|
||||
"RL": _list_release,
|
||||
"GS": _scene_go,
|
||||
"HS": _scene_halt,
|
||||
"RS": _scene_release
|
||||
}
|
79
README.md
79
README.md
|
@ -1,21 +1,16 @@
|
|||
# Bacon Script
|
||||
|
||||
A theoretical exersise to control a Hog 4 via OSC, with comment macros.
|
||||
A theoretical exercise to control a Hog 4 via OSC, with comment macros.
|
||||
|
||||
The comment macro grammer 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 freatures, like timing, are not yet implemented. Refer to the **Features** table for specific notes.
|
||||
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.
|
||||
|
||||
## Installing
|
||||
|
||||
Install Python-OSC for output.
|
||||
Install Antlr4 for input and Python-OSC for output.
|
||||
```bash
|
||||
$ pip install python-osc
|
||||
```
|
||||
|
||||
Install Antlr4 for input.
|
||||
```bash
|
||||
$ pip install antlr4-python3-runtime
|
||||
$ pip3 install antlr4-python3-runtime python-osc
|
||||
```
|
||||
|
||||
Use git to retrieve a copy of the code.
|
||||
|
@ -28,14 +23,21 @@ $ cd baconscript
|
|||
|
||||
Edit `server.cfg` to the correct values for your Hog4.
|
||||
|
||||
`comment.py` will accept macros on the command line, or will run an interactive prompt.
|
||||
`comment.py` will accept macros on the command line, or will run an interactive prompt. Use the builtin command `exit` to quit the interactive prompt.
|
||||
|
||||
```bash
|
||||
$ ./comment.py
|
||||
comment#
|
||||
Adding Hog device at net# 1
|
||||
comment# GL1
|
||||
Go on List 1
|
||||
comment# exit
|
||||
```
|
||||
|
||||
Use the builtin command `exit` to quit the interacive prompt.
|
||||
Run a baconscript file by passing the script file to `comment.py` as standard input.
|
||||
|
||||
```bash
|
||||
$ ./comment.py < example.bs
|
||||
```
|
||||
|
||||
## Developing
|
||||
|
||||
|
@ -51,26 +53,35 @@ $ antlr -Dlanguage=Python3 CommentMacro.g4
|
|||
|
||||
|
||||
## Features
|
||||
Only features that are supported in both OSC and Comment Macros are able to be implimented in baconscript. This table lists all comment macros (as of 3.9) that are implimented in python.
|
||||
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 implemented in python.
|
||||
|
||||
| Grammar Feature | eg. | Supported |
|
||||
| ----------------|-----|-----------|
|
||||
| fade times | t5 | no |
|
||||
| multiple targets | 1,2 | Yes |
|
||||
| ranges | 1>4 | Yes, intigers only |
|
||||
| ranges | 1>4 | Yes, intervals of 1 |
|
||||
| multiple macros | GM1:GL3 | Yes |
|
||||
| network devies | h4 | Yes, H devies only |
|
||||
| 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 | no | |
|
||||
| RM | Release Master | no | |
|
||||
| RA | Relase All | no | |
|
||||
| AM | Assert Master | Partial | on current master only |
|
||||
| RM | Release Master | Partial | on current master only |
|
||||
| RA | Release All | Yes | |
|
||||
| RO | Release Others | no | |
|
||||
| FM | Fade Master | Yes | no times, no *
|
||||
| FGM | Fade Grand Master | Yes | no times
|
||||
| FM | Fade Master | Partial | no times, no * |
|
||||
| FGM | Fade Grand Master | Partial | no times |
|
||||
| CM | Choose Master | Yes | |
|
||||
| GL | Go List | Yes | |
|
||||
| HL | Halt List | Yes | |
|
||||
|
@ -84,7 +95,7 @@ Only features that are supported in both OSC and Comment Macros are able to be i
|
|||
| HS | Halt Scene | Yes | |
|
||||
| AS | Assert Scene | no | |
|
||||
| RS | Release Scene | Yes | |
|
||||
| CP | Change Page | no | |
|
||||
| CP | Change Page | Partial | only CP+ and CP- |
|
||||
| RV | Recall View | no | |
|
||||
| ET | Enable Timecode | no | |
|
||||
| DT | Disable Timecode | no | |
|
||||
|
@ -92,14 +103,28 @@ Only features that are supported in both OSC and Comment Macros are able to be i
|
|||
| MS | Midi String | no | possible? |
|
||||
| MN | Midi Note | no | |
|
||||
| RN | Reset Node | no | |
|
||||
| GK | Go Keystroke Macro | no | |
|
||||
| HK | Pause Keystroke Macro | no | |
|
||||
| RK | Stop Keystroke Macro | no | . |
|
||||
| GK | Go Keystroke Macro | Yes | |
|
||||
| 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 batches
|
||||
* Sending target ranges as OSC arguments
|
||||
* 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)
|
77
comment.py
77
comment.py
|
@ -1,77 +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 readline
|
||||
import signal
|
||||
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)
|
||||
|
||||
|
||||
def orderly_exit():
|
||||
logger.info('Goodbye.')
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
signal.signal(signal.SIGINT, orderly_exit)
|
||||
if len(sys.argv) > 1:
|
||||
logger.debug("found macro at argv[1]")
|
||||
comment(sys.argv[1])
|
||||
else:
|
||||
while True:
|
||||
text = input("comment# ")
|
||||
if text == 'exit':
|
||||
orderly_exit()
|
||||
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