Post sonoptik commit
This commit is contained in:
commit
ab868905b3
109 changed files with 22885 additions and 0 deletions
BIN
clitools/generators/.DS_Store
vendored
Normal file
BIN
clitools/generators/.DS_Store
vendored
Normal file
Binary file not shown.
2407
clitools/generators/159.gml
Executable file
2407
clitools/generators/159.gml
Executable file
File diff suppressed because it is too large
Load diff
2791
clitools/generators/160.gml
Executable file
2791
clitools/generators/160.gml
Executable file
File diff suppressed because it is too large
Load diff
2873
clitools/generators/OSC3.py
Normal file
2873
clitools/generators/OSC3.py
Normal file
File diff suppressed because it is too large
Load diff
BIN
clitools/generators/__pycache__/OSC3.cpython-38.pyc
Normal file
BIN
clitools/generators/__pycache__/OSC3.cpython-38.pyc
Normal file
Binary file not shown.
BIN
clitools/generators/__pycache__/turtle.cpython-38.pyc
Normal file
BIN
clitools/generators/__pycache__/turtle.cpython-38.pyc
Normal file
Binary file not shown.
53
clitools/generators/blank.py
Executable file
53
clitools/generators/blank.py
Executable file
|
|
@ -0,0 +1,53 @@
|
|||
#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# -*- mode: Python -*-
|
||||
|
||||
|
||||
'''
|
||||
|
||||
Send only black points
|
||||
v0.1.0
|
||||
|
||||
Use it to test your filters and outputs
|
||||
|
||||
LICENCE : CC
|
||||
|
||||
by cocoa
|
||||
|
||||
'''
|
||||
|
||||
from __future__ import print_function
|
||||
import time
|
||||
import argparse
|
||||
import sys
|
||||
name="generator::dummy"
|
||||
|
||||
|
||||
def debug(*args, **kwargs):
|
||||
if( verbose == False ):
|
||||
return
|
||||
print(*args, file=sys.stderr, **kwargs)
|
||||
|
||||
argsparser = argparse.ArgumentParser(description="dummy generator")
|
||||
argsparser.add_argument("-f","--fps",help="Frame Per Second",default=30,type=int)
|
||||
argsparser.add_argument("-v","--verbose",action="store_true",help="Verbose output")
|
||||
args = argsparser.parse_args()
|
||||
|
||||
fps=args.fps
|
||||
verbose=args.verbose
|
||||
optimal_looptime = 1 / fps
|
||||
debug(name+" optimal looptime "+str(optimal_looptime))
|
||||
|
||||
|
||||
shape = [[400,400,0],[400,400,64],[400,400,0]]
|
||||
|
||||
|
||||
while True:
|
||||
start = time.time()
|
||||
print(shape, flush=True);
|
||||
looptime = time.time() - start
|
||||
if( looptime < optimal_looptime ):
|
||||
time.sleep( optimal_looptime - looptime)
|
||||
debug(name+" micro sleep:"+str( optimal_looptime - looptime))
|
||||
|
||||
|
||||
BIN
clitools/generators/book2.ild
Executable file
BIN
clitools/generators/book2.ild
Executable file
Binary file not shown.
54
clitools/generators/brmlab1.svg
Executable file
54
clitools/generators/brmlab1.svg
Executable file
|
|
@ -0,0 +1,54 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xml:space="preserve"
|
||||
height="53"
|
||||
width="299.96875"
|
||||
version="1.1"
|
||||
id="svg2"
|
||||
inkscape:version="0.48.0 r9654"
|
||||
sodipodi:docname="brmlab1.svg"
|
||||
inkscape:export-filename="/home/prusnak/work/scm/laserdisplay/svglaser/templates/template3.svg.png"
|
||||
inkscape:export-xdpi="200"
|
||||
inkscape:export-ydpi="200"><defs
|
||||
id="defs2988" /><metadata
|
||||
id="metadata78"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1024"
|
||||
inkscape:window-height="689"
|
||||
id="namedview76"
|
||||
showgrid="false"
|
||||
inkscape:zoom="1"
|
||||
inkscape:cx="-2.5851173"
|
||||
inkscape:cy="-55.600814"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="25"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg2"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:snap-global="true"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0" />
|
||||
<path
|
||||
id="path20"
|
||||
style="fill:none;stroke:#000000;stroke-opacity:1"
|
||||
d="m 137.17375,22.4425 c 0,-1.815 5.24,-4.345 13.73375,-4.345 3.94875,0 7.73,0.59 10.37875,1.62 2.085,0.81125 3.32875,1.83 3.32875,2.725 0,9.0725 0.0188,30.05375 0.0188,30.05375 l 5.87245,-0.004 c 0,-10e-4 -0.0175,-20.97875 -0.0175,-30.05 0,-2.035 -0.9175,-5.805 -7.0725,-8.2 -3.35125,-1.3025 -7.7925,-2.01875 -12.50875,-2.01875 -4.71625,0 -9.15875,0.71625 -12.50875,2.01875 -1.7975,0.7 -3.16375,1.50625 -4.175,2.3625 -1.01,-0.8475 -2.3675,-1.66875 -4.15,-2.3625 -3.34875,-1.3025 -7.79125,-2.01875 -12.50875,-2.01875 -4.715,0 -9.15625,0.71625 -12.50625,2.01875 -6.15625,2.395 -7.075,6.165 -7.075,8.2 0,9.8775 -0.0163,30.04875 -0.0163,30.04875 l 5.87375,0.005 c 0,0 0.0175,-20.17375 0.0175,-30.05375 0,-1.815 5.215,-4.345 13.70625,-4.345 3.94875,0 7.73125,0.59 10.38,1.62 2.08375,0.81125 3.32875,1.83 3.32875,2.725 0,9.0725 0.0175,30.0575 0.0175,30.0575 l 5.87375,-0.005 c 0,0 0.009,-20.98125 0.009,-30.0525 M 93.61125,18.3922 c -1.0075,-1.47125 -2.7675,-2.98 -5.79125,-4.15625 -3.35,-1.3025 -7.79375,-2.02 -12.50875,-2.02 -4.715,0 -9.15875,0.7175 -12.5075,2.02 C 56.64875,16.63 55.73,20.4 55.73,22.435 c 0,9.87875 -0.0175,30.04875 -0.0175,30.04875 l 5.87375,0.005 c 0,0 0.0175,-20.17375 0.0175,-30.05375 0,-1.81375 5.21375,-4.345 13.7075,-4.345 3.9475,0 7.73,0.59 10.37875,1.62125 1.58875,0.6175 2.6875,1.355 3.1225,2.0675 l 4.79875,-3.38625 z m 86.2125,34.1 5.874,0 0,-52.0075 -5.874,0 0,52.0075 z m 24.45,-33.325 c -0.89625,0 -1.91375,1.24375 -2.725,3.32875 -1.03,2.64875 -1.62125,6.43125 -1.62125,10.37875 0,8.4925 2.53125,13.7075 4.34625,13.7075 7.19625,0 24.94,0.0225 31.975,0.0313 l 0,-27.44625 -31.975,0 z m 37.84875,33.32875 -2.94,-0.004 c 0,0 -25.83625,-0.035 -34.90875,-0.035 -2.035,0 -5.80625,-0.91875 -8.2,-7.07375 -1.3025,-3.35125 -2.02,-7.7925 -2.02,-12.50875 0,-4.715 0.7175,-9.1575 2.02,-12.5075 2.39375,-6.155 6.165,-7.075 8.2,-7.075 l 34.9125,0 2.91979,0.006 0.0165,39.198 z m 49.85125,-9.24125 c -0.80875,2.085 -1.82875,3.32875 -2.7225,3.32875 -7.1975,0 -24.94125,0.0225 -31.97625,0.0313 l 0,-27.4475 31.97625,0.001 c 1.81375,0 4.345,5.215 4.345,13.7075 0,3.94625 -0.5925,7.73 -1.6225,10.37875 M 297.45,20.3687 c -2.39375,-6.155 -6.165,-7.075 -8.19875,-7.075 l -31.97625,-0.002 0,-12.80625 -5.87375,0 0,52.0125 2.94125,-0.004 c 0,0 25.83625,-0.0362 34.90875,-0.0362 2.03375,0 5.805,-0.9175 8.19875,-7.0725 1.30375,-3.35125 2.02,-7.7925 2.02,-12.50875 0,-4.715 -0.71625,-9.1575 -2.02,-12.5075 M 41.07375,43.255 c -0.80875,2.085 -1.82875,3.32875 -2.725,3.32875 -7.195,0 -24.94,0.0225 -31.97375,0.0313 l 0,-27.4475 31.97375,0.001 c 1.815,0 4.34625,5.215 4.34625,13.7075 0,3.94625 -0.5925,7.73 -1.62125,10.37875 m 5.475,-22.88625 c -2.39375,-6.155 -6.16375,-7.075 -8.2,-7.075 l -31.97375,-0.002 0,-12.80625 -5.875,0 0,52.0125 2.9425,-0.004 c 0,0 25.835,-0.0362 34.90625,-0.0362 2.03625,0 5.80625,-0.9175 8.2,-7.0725 1.30375,-3.35125 2.02,-7.7925 2.02,-12.50875 0,-4.715 -0.71625,-9.1575 -2.02,-12.5075"
|
||||
inkscape:connector-curvature="0" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.6 KiB |
53
clitools/generators/brmlab2.svg
Executable file
53
clitools/generators/brmlab2.svg
Executable file
|
|
@ -0,0 +1,53 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xml:space="preserve"
|
||||
height="78.96875"
|
||||
width="78.96875"
|
||||
version="1.1"
|
||||
id="svg2"
|
||||
inkscape:version="0.48.0 r9654"
|
||||
sodipodi:docname="brmlab2.svg"
|
||||
inkscape:export-filename="/home/prusnak/work/scm/laserdisplay/svglaser/templates/template4.svg.png"
|
||||
inkscape:export-xdpi="200"
|
||||
inkscape:export-ydpi="200"><defs
|
||||
id="defs2994" /><metadata
|
||||
id="metadata78"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1024"
|
||||
inkscape:window-height="689"
|
||||
id="namedview76"
|
||||
showgrid="false"
|
||||
inkscape:zoom="1"
|
||||
inkscape:cx="25.043829"
|
||||
inkscape:cy="5.6960585"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="25"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg2"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:snap-global="true"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0" />
|
||||
<path
|
||||
id="path3237"
|
||||
style="fill:none;stroke:#000000;stroke-width:1"
|
||||
d="m 20.26276,45.39193 c -1.816875,0 -3.293437,-1.4775 -3.293437,-3.29344 0,-1.81593 1.476562,-3.29437 3.293437,-3.29437 1.816875,0 3.294375,1.47844 3.294375,3.29437 0,1.81594 -1.4775,3.29344 -3.294375,3.29344 M 39.480011,0.50605 C 17.985519,0.50605 0.5,17.99425 0.5,39.48874 c 0,10.41205 4.0546519,20.20071 11.416975,27.56304 7.363668,7.36232 17.15099,11.41697 27.563036,11.41697 21.494491,0 38.982697,-17.48686 38.982697,-38.98001 C 78.461408,17.99291 60.974502,0.50605 39.480011,0.50605 m -0.09362,68.75171 c -5.945327,0 -11.681286,-1.74473 -16.588197,-5.04528 l -0.998709,-0.67022 0.765276,-0.92531 c 1.473999,-1.78685 1.350062,-4.36785 -0.289986,-6.0079 -0.844692,-0.84469 -1.96854,-1.31035 -3.163381,-1.31035 -1.037214,0 -2.046752,0.36218 -2.843313,1.01916 l -0.926513,0.76407 -0.670218,-0.9963 C 6.757481,44.32012 8.3000651,28.49238 18.341303,18.45235 c 4.199391,-4.2018 9.490142,-7.02345 15.299501,-8.16174 l 1.179198,-0.22982 0.115514,1.19484 c 0.220197,2.30425 2.13459,4.04176 4.452076,4.04176 2.317487,0 4.23188,-1.73751 4.45328,-4.04176 l 0.115513,-1.19484 1.177996,0.22982 c 5.806952,1.13829 11.098906,3.95994 15.299501,8.15933 10.040034,10.04124 11.583822,25.87018 3.668751,37.63569 l -0.670218,0.9963 -0.92531,-0.76527 c -0.798967,-0.65698 -1.807302,-1.01796 -2.845719,-1.01796 -1.194841,0 -2.317486,0.46446 -3.163381,1.30915 -1.638845,1.64005 -1.762781,4.22225 -0.289986,6.0091 l 0.764072,0.92531 -0.996302,0.67022 c -4.90691,3.30055 -10.644073,5.04528 -16.5894,5.04528 m -7.130784,-26.72605 14.281498,0 0,-6.00112 -14.281498,0 0,6.00112 z M 24.122448,30.11568 c -1.816875,0 -3.294375,-1.4775 -3.294375,-3.29344 0,-1.81593 1.4775,-3.29437 3.294375,-3.29437 1.815937,0 3.293437,1.47844 3.293437,3.29437 0,1.81594 -1.4775,3.29344 -3.293437,3.29344 m 34.387656,15.27625 c -1.815937,0 -3.294375,-1.4775 -3.294375,-3.29344 0,-1.81593 1.478438,-3.29437 3.294375,-3.29437 1.816875,0 3.294375,1.47844 3.294375,3.29437 0,1.81594 -1.4775,3.29344 -3.294375,3.29344 m -26.905937,15.1875 c -1.815938,0 -3.292501,-1.4775 -3.292501,-3.29344 0,-1.81593 1.476563,-3.29437 3.292501,-3.29437 1.816875,0 3.294374,1.47844 3.294374,3.29437 0,1.81594 -1.477499,3.29344 -3.294374,3.29344 M 54.647291,30.11568 c -1.816874,0 -3.294374,-1.4775 -3.294374,-3.29344 0,-1.81593 1.4775,-3.29437 3.294374,-3.29437 1.815938,0 3.292501,1.47844 3.292501,3.29437 0,1.81594 -1.476563,3.29344 -3.292501,3.29344 m -7.474843,30.46375 c -1.816875,0 -3.294375,-1.4775 -3.294375,-3.29344 0,-1.81593 1.4775,-3.29437 3.294375,-3.29437 1.815937,0 3.293437,1.47844 3.293437,3.29437 0,1.81594 -1.4775,3.29344 -3.293437,3.29344 m -7.775,-30.46375 c -1.816875,0 -3.294375,-1.4775 -3.294375,-3.29344 0,-1.81593 1.4775,-3.29437 3.294375,-3.29437 1.815937,0 3.293437,1.47844 3.293437,3.29437 0,1.81594 -1.4775,3.29344 -3.293437,3.29344"
|
||||
inkscape:connector-curvature="0" /></svg>
|
||||
|
After Width: | Height: | Size: 4.5 KiB |
85
clitools/generators/dummy.py
Executable file
85
clitools/generators/dummy.py
Executable file
|
|
@ -0,0 +1,85 @@
|
|||
#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# -*- mode: Python -*-
|
||||
|
||||
|
||||
'''
|
||||
|
||||
This is the most basic generator you can imagine: straight up static!
|
||||
v0.1.0
|
||||
|
||||
Use it to test your filters and outputs
|
||||
|
||||
LICENCE : CC
|
||||
|
||||
by cocoa
|
||||
|
||||
'''
|
||||
|
||||
from __future__ import print_function
|
||||
import time
|
||||
import argparse
|
||||
import sys
|
||||
name="generator::dummy"
|
||||
|
||||
|
||||
def debug(*args, **kwargs):
|
||||
if( verbose == False ):
|
||||
return
|
||||
print(*args, file=sys.stderr, **kwargs)
|
||||
|
||||
argsparser = argparse.ArgumentParser(description="dummy generator")
|
||||
argsparser.add_argument("-f","--fps",help="Frame Per Second",default=30,type=int)
|
||||
argsparser.add_argument("-s","--speed",help="point per frame progress",default=3,type=int)
|
||||
argsparser.add_argument("-v","--verbose",action="store_true",help="Verbose output")
|
||||
args = argsparser.parse_args()
|
||||
|
||||
fps=args.fps
|
||||
verbose=args.verbose
|
||||
optimal_looptime = 1 / fps
|
||||
debug(name+" optimal looptime "+str(optimal_looptime))
|
||||
color = 16777215
|
||||
square = [[100.0, 100.0, color], [100.0, 500.0, color], [500.0, 500.0, color], [500.0, 100.0, color], [100.0, 100.0, color]]
|
||||
line =[]
|
||||
for i in range(00,800,int(800/120)):
|
||||
line.append([i, 400, color])
|
||||
square = [[100.0, 100.0, color], [100.0, 500.0, color], [500.0, 500.0, color], [500.0, 100.0, color], [100.0, 100.0, color]]
|
||||
mire = [
|
||||
[600,600,0],
|
||||
[600,600,color],
|
||||
[700,600,color],
|
||||
[700,700,color],
|
||||
[600,700,color],
|
||||
[600,600,color],
|
||||
[100,100,0],
|
||||
[100,100,color],
|
||||
[200,100,color],
|
||||
[200,200,color],
|
||||
[100,200,color],
|
||||
[100,100,color],
|
||||
[0,0,0],
|
||||
[0,0,color],
|
||||
[800,0,color],
|
||||
[800,800,color],
|
||||
[0,800,color],
|
||||
[0,0,color],
|
||||
[350,400,0],
|
||||
[350,400,color],
|
||||
[450,400,color],
|
||||
[400,350,0],
|
||||
[400,350,color],
|
||||
[400,450,color],
|
||||
]
|
||||
|
||||
shape = mire
|
||||
|
||||
|
||||
while True:
|
||||
start = time.time()
|
||||
print(shape, flush=True);
|
||||
looptime = time.time() - start
|
||||
if( looptime < optimal_looptime ):
|
||||
time.sleep( optimal_looptime - looptime)
|
||||
debug(name+" micro sleep:"+str( optimal_looptime - looptime))
|
||||
|
||||
|
||||
182
clitools/generators/example.py
Executable file
182
clitools/generators/example.py
Executable file
|
|
@ -0,0 +1,182 @@
|
|||
#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# -*- mode: Python -*-
|
||||
|
||||
|
||||
'''
|
||||
|
||||
example, based on custom
|
||||
v0.1.0
|
||||
|
||||
A copy of square.py you can modify to code your plugin.
|
||||
custom1 has necessary hooks in LJ.conf, webui and so on.
|
||||
|
||||
|
||||
LICENCE : CC
|
||||
|
||||
by Sam Neurohack
|
||||
|
||||
|
||||
'''
|
||||
import sys
|
||||
import os
|
||||
ljpath = r'%s' % os.getcwd().replace('\\','/')
|
||||
|
||||
# import from shell
|
||||
sys.path.append(ljpath +'/../../libs/')
|
||||
|
||||
#import from LJ
|
||||
sys.path.append(ljpath +'/libs/')
|
||||
print(ljpath+'/../libs/')
|
||||
|
||||
import lj23layers as lj
|
||||
|
||||
sys.path.append('../libs')
|
||||
import math
|
||||
import time
|
||||
import argparse
|
||||
|
||||
|
||||
print ("")
|
||||
print ("Arguments parsing if needed...")
|
||||
argsparser = argparse.ArgumentParser(description="Custom1 example for LJ")
|
||||
argsparser.add_argument("-v","--verbose",help="Verbosity level (0 by default)",default=0,type=int)
|
||||
args = argsparser.parse_args()
|
||||
|
||||
# Useful variables init.
|
||||
white = lj.rgb2int(255,255,255)
|
||||
red = lj.rgb2int(255,0,0)
|
||||
blue = lj.rgb2int(0,0,255)
|
||||
green = lj.rgb2int(0,255,0)
|
||||
|
||||
width = 800
|
||||
height = 600
|
||||
centerX = width / 2
|
||||
centerY = height / 2
|
||||
|
||||
# 3D to 2D projection parameters
|
||||
fov = 256
|
||||
viewer_distance = 2.2
|
||||
|
||||
# Anaglyph computation parameters for right and left eyes.
|
||||
# algorythm come from anaglyph geo maps
|
||||
eye_spacing = 100
|
||||
nadir = 0.5
|
||||
observer_altitude = 30000
|
||||
map_layerane_altitude = 0.0
|
||||
|
||||
# square coordinates : vertices that compose each of the square.
|
||||
vertices = [
|
||||
(- 1.0, 1.0,- 1.0),
|
||||
( 1.0, 1.0,- 1.0),
|
||||
( 1.0,- 1.0,- 1.0),
|
||||
(- 1.0,- 1.0,- 1.0)
|
||||
]
|
||||
|
||||
face = [0,1,2,3]
|
||||
|
||||
#
|
||||
# LJ inits
|
||||
#
|
||||
|
||||
layer = 0
|
||||
|
||||
# Define properties for each drawn "element" : name, intensity, active, xy, color, red, green, blue, layer , closed
|
||||
Leftsquare = lj.FixedObject('Leftsquare', True, 255, [], red, 255, 0, 0, layer , True)
|
||||
Rightsquare = lj.FixedObject('Rightsquare', True, 255, [], green, 0, 255, 0, layer , True)
|
||||
|
||||
# 'Destination' for given layer : name, number, active, layer , scene, laser
|
||||
Dest0 = lj.DestObject('0', 0, True, 0 , 0, 0) # Dest0 will send layer 0 points to scene 0, laser 0
|
||||
|
||||
|
||||
#
|
||||
# Anaglyph computation : different X coordinate for each eye
|
||||
#
|
||||
|
||||
def LeftShift(elevation):
|
||||
|
||||
diff = elevation - map_layerane_altitude
|
||||
return nadir * eye_spacing * diff / (observer_altitude - elevation)
|
||||
|
||||
def RightShift(elevation):
|
||||
|
||||
diff = map_layerane_altitude - elevation
|
||||
return (1 - nadir) * eye_spacing * diff / (observer_altitude - elevation)
|
||||
|
||||
|
||||
def Proj(x,y,z,angleX,angleY,angleZ):
|
||||
|
||||
rad = angleX * math.pi / 180
|
||||
cosa = math.cos(rad)
|
||||
sina = math.sin(rad)
|
||||
y2 = y
|
||||
y = y2 * cosa - z * sina
|
||||
z = y2 * sina + z * cosa
|
||||
|
||||
rad = angleY * math.pi / 180
|
||||
cosa = math.cos(rad)
|
||||
sina = math.sin(rad)
|
||||
z2 = z
|
||||
z = z2 * cosa - x * sina
|
||||
x = z2 * sina + x * cosa
|
||||
|
||||
rad = angleZ * math.pi / 180
|
||||
cosa = math.cos(rad)
|
||||
sina = math.sin(rad)
|
||||
x2 = x
|
||||
x = x2 * cosa - y * sina
|
||||
y = x2 * sina + y * cosa
|
||||
|
||||
|
||||
""" Transforms this 3D point to 2D using a perspective projection. """
|
||||
factor = fov / (viewer_distance + z)
|
||||
x = x * factor + centerX
|
||||
y = - y * factor + centerY
|
||||
return (x,y)
|
||||
|
||||
|
||||
#
|
||||
# Main
|
||||
#
|
||||
|
||||
def Run():
|
||||
Left = []
|
||||
Right = []
|
||||
counter =0
|
||||
try:
|
||||
while True:
|
||||
Left = []
|
||||
Right = []
|
||||
x = vertices[0][0]
|
||||
y = vertices[0][1]
|
||||
z = vertices[0][2]
|
||||
|
||||
# lj tracers will "move" the laser to this first point in black, then move to the next with second point color.
|
||||
# for more accuracy in dac emulator, repeat this first point.
|
||||
|
||||
# generate all points in square.
|
||||
for point in face:
|
||||
x = vertices[point][0]
|
||||
y = vertices[point][1]
|
||||
z = vertices[point][2]
|
||||
left.append(proj(x+leftshift(z*25),y,z,0,counter,0))
|
||||
right.append(proj(x+rightshift(z*25),y,z,0,counter,0))
|
||||
|
||||
|
||||
lj.polylineonecolor(left, c = leftsquare.color , layer = leftsquare.layer, closed = leftsquare.closed)
|
||||
lj.polylineonecolor(right, c = rightsquare.color , layer = rightsquare.layer, closed = rightsquare.closed)
|
||||
lj.drawdests()
|
||||
time.sleep(0.1)
|
||||
counter += 1
|
||||
if counter > 360:
|
||||
counter = 0
|
||||
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
|
||||
# Gently stop on CTRL C
|
||||
finally:
|
||||
lj.ClosePlugin()
|
||||
|
||||
|
||||
Run()
|
||||
406
clitools/generators/fromGML.py
Normal file
406
clitools/generators/fromGML.py
Normal file
|
|
@ -0,0 +1,406 @@
|
|||
#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# -*- mode: Python -*-
|
||||
|
||||
'''
|
||||
|
||||
fromGML
|
||||
v0.1.0
|
||||
|
||||
Display a GML file
|
||||
|
||||
See GML specs at the end.
|
||||
Support the gml spec="1.0 (minimum)"
|
||||
and header/client/name
|
||||
and maybe one day drawing/brush/color
|
||||
|
||||
LICENCE : CC
|
||||
by cocoa and Sam Neurohack
|
||||
|
||||
Heavy use of : https://github.com/kgn/pygml
|
||||
'''
|
||||
from __future__ import print_function
|
||||
import time
|
||||
import struct
|
||||
import argparse
|
||||
import sys
|
||||
import xml.etree.ElementTree as etree
|
||||
#import urllib
|
||||
from datetime import datetime
|
||||
import math, random
|
||||
import ast
|
||||
|
||||
name="generator::fromgml"
|
||||
|
||||
|
||||
def debug(*args, **kwargs):
|
||||
if( verbose == False ):
|
||||
return
|
||||
print(*args, file=sys.stderr, **kwargs)
|
||||
|
||||
argsparser = argparse.ArgumentParser(description="GML file frame generator")
|
||||
argsparser.add_argument("-f","--fps",help="Frame Per Second",default=30,type=int)
|
||||
argsparser.add_argument("-v","--verbose",action="store_true",help="Verbose output")
|
||||
argsparser.add_argument("-g","--gml",help=".gml file",default="147.gml",type=str)
|
||||
argsparser.add_argument("-t","--total",help="Total time",default=32,type=int)
|
||||
argsparser.add_argument("-m","--mode",help="once or anim mode",default="anim",type=str)
|
||||
argsparser.add_argument("-s","--skip",help="% of points to skip",default="0.4",type=float)
|
||||
argsparser.add_argument("-r","--rot",help="(angleX, angleY, angleZ) in degree",default="(0,0,270)",type=str)
|
||||
args = argsparser.parse_args()
|
||||
|
||||
fps=args.fps
|
||||
verbose=args.verbose
|
||||
mode = args.mode
|
||||
optimal_looptime = 1 / fps
|
||||
angles = ast.literal_eval(args.rot)
|
||||
debug(name+" optimal frame time "+str(optimal_looptime))
|
||||
|
||||
|
||||
TOTAL_TIME=float(args.total)
|
||||
TIME_STRETCH = 1
|
||||
ZOOM=1.0
|
||||
DELTA = 7
|
||||
width = 500
|
||||
height = 500
|
||||
centerX = width / 2
|
||||
centerY = height / 2
|
||||
# 3D to 2D projection parameters
|
||||
fov = 200
|
||||
viewer_distance = 2.2
|
||||
|
||||
skip = args.skip
|
||||
#skip is the percentage of points that we ignore in order to render
|
||||
# faster in the laser display. Unfortunately we are not able to render too
|
||||
# complex content in our display without resulting in a lot of blinking.
|
||||
|
||||
# return a list with all points
|
||||
def readGML(filename):
|
||||
|
||||
outputData = []
|
||||
tree = etree.parse(filename)
|
||||
root = tree.getroot()
|
||||
'''
|
||||
if (root.tag.lower() != "gml"):
|
||||
print("Not a GML file.")
|
||||
return
|
||||
'''
|
||||
#~
|
||||
tag = root.find("tag")
|
||||
header = tag.find("header")
|
||||
if header != None:
|
||||
client = header.find("client")
|
||||
if client != None:
|
||||
debug("Graffiti name :", client.find("name").text)
|
||||
drawing = tag.find("drawing")
|
||||
environment = header.find("environment")
|
||||
if not environment:
|
||||
environment = tag.find("environment")
|
||||
#screenBounds = environment.find("screenBounds")
|
||||
#globalScale = (1.0,1.0,1.0)
|
||||
#dim = (float(screenBounds.find("x").text) * globalScale[0], float(screenBounds.find("y").text) * globalScale[1], float(screenBounds.find("z").text) * globalScale[2])
|
||||
#dim = (40.0,40.0,40.0)
|
||||
#~
|
||||
strokes = drawing.findall("stroke")
|
||||
for stroke in strokes:
|
||||
pointsEl = stroke.findall("pt")
|
||||
for pointEl in pointsEl:
|
||||
|
||||
x = float(pointEl.find("x").text) - 0.5
|
||||
y = float(pointEl.find("y").text) - 0.5
|
||||
z = float(pointEl.find("z").text) - 0.5
|
||||
transpoint = Rot(x,y,z,angles[0],angles[1],angles[2])
|
||||
x = (transpoint[0]*ZOOM*width/2) + (width/2)
|
||||
y = (transpoint[1]*ZOOM*height/2) + (height/2)
|
||||
z = transpoint[2]
|
||||
# WIDTH/2 + ZOOM*point[0]*WIDTH/2, HEIGHT/2 + ZOOM*point[1]*HEIGHT/2
|
||||
time = float(pointEl.find("time").text)
|
||||
outputData.append([x,y,z,time])
|
||||
#print(outputData)
|
||||
return outputData
|
||||
|
||||
def Rot(x, y, z, angleX, angleY, angleZ):
|
||||
|
||||
rad = angleX * math.pi / 180
|
||||
cosa = math.cos(rad)
|
||||
sina = math.sin(rad)
|
||||
y2 = y
|
||||
y = y2 * cosa - z * sina
|
||||
z = y2 * sina + z * cosa
|
||||
|
||||
rad = angleY * math.pi / 180
|
||||
cosa = math.cos(rad)
|
||||
sina = math.sin(rad)
|
||||
z2 = z
|
||||
z = z2 * cosa - x * sina
|
||||
x = z2 * sina + x * cosa
|
||||
|
||||
rad = angleZ * math.pi / 180
|
||||
cosa = math.cos(rad)
|
||||
sina = math.sin(rad)
|
||||
x2 = x
|
||||
x = x2 * cosa - y * sina
|
||||
y = x2 * sina + y * cosa
|
||||
|
||||
return (x,y,z)
|
||||
|
||||
|
||||
#[x,y,z,time]
|
||||
def iterPoints():
|
||||
|
||||
for point in gml:
|
||||
yield point
|
||||
|
||||
|
||||
# Play once during total time arg
|
||||
def Once():
|
||||
|
||||
debug(name,"play once mode")
|
||||
shape = []
|
||||
for point in gml:
|
||||
shape.append([point[0],point[1], 65535])
|
||||
debug(name + str(shape))
|
||||
|
||||
t0=datetime.now()
|
||||
deltat=0
|
||||
|
||||
while deltat<TOTAL_TIME:
|
||||
|
||||
start = time.time()
|
||||
print(shape, flush=True);
|
||||
looptime = time.time() - start
|
||||
|
||||
if( looptime < optimal_looptime ):
|
||||
time.sleep( optimal_looptime - looptime)
|
||||
debug(name+" micro sleep:"+str( optimal_looptime - looptime))
|
||||
|
||||
delta = datetime.now() - t0
|
||||
deltat = delta.seconds + delta.microseconds/1000000.0
|
||||
deltat = float(deltat)/TIME_STRETCH
|
||||
|
||||
|
||||
# Anim
|
||||
def Anim():
|
||||
|
||||
debug(name+" anim mode")
|
||||
t0=datetime.now()
|
||||
deltat = 0
|
||||
|
||||
while deltat<TOTAL_TIME:
|
||||
|
||||
delta = datetime.now() - t0
|
||||
deltat = delta.seconds + delta.microseconds/1000000.0
|
||||
deltat = float(deltat)/TIME_STRETCH
|
||||
|
||||
if deltat > TOTAL_TIME:
|
||||
t0=datetime.now()
|
||||
|
||||
first=True
|
||||
shape = []
|
||||
for point in iterPoints():
|
||||
if point[3] <= deltat and deltat <= point[3]+DELTA and random.random()<(1-skip):
|
||||
if first:
|
||||
first=False
|
||||
else:
|
||||
#LD.draw_point(WIDTH/2 + ZOOM*point.x*WIDTH/2, HEIGHT/2 + ZOOM*point.y*HEIGHT/2)
|
||||
shape.append([point[0], point[1], 65535])
|
||||
print(shape, flush=True);
|
||||
|
||||
|
||||
debug(name + " Reading : "+args.gml+" in "+mode+" mode.")
|
||||
gml = readGML(args.gml)
|
||||
|
||||
debug(name + " total points : "+ str(len(gml)))
|
||||
|
||||
if mode =="once":
|
||||
Once()
|
||||
else:
|
||||
Anim()
|
||||
|
||||
debug(name + " ends.")
|
||||
exit()
|
||||
'''
|
||||
|
||||
<gml spec="1.0 (minimum)">
|
||||
|
||||
<tag>
|
||||
<drawing>
|
||||
<stroke>
|
||||
<pt>
|
||||
<x>0.0</x>
|
||||
<y>0.0</y>
|
||||
</pt>
|
||||
</stroke>
|
||||
</drawing>
|
||||
</tag>
|
||||
|
||||
</gml>
|
||||
|
||||
|
||||
|
||||
<gml spec="1.0">
|
||||
|
||||
<tag>
|
||||
|
||||
<header>
|
||||
|
||||
<client> <!-- how, who, what and where -->
|
||||
<name>Laser Tag</name> <!-- application name -->
|
||||
<version>2.0</version> <!-- application version -->
|
||||
<username>MyUserName</username> <!-- user name on 000000book.com, optional -->
|
||||
<permalink>http://000000book.com/data/156/</permalink> <!-- URL to .gml data on 000000book.com, optional -->
|
||||
<keywords>katsu,paris,2010</keywords> <!-- comma-separated -->
|
||||
<uniquekey>28sks922ks992</uniquekey> <!-- iPhone uuid, MAC address, etc -->
|
||||
<ip>192.168.1.1</ip>
|
||||
<time>1928372722</time> <!-- unixtime -->
|
||||
<location>
|
||||
<lon>-39.392922</lon>
|
||||
<lat>53.29292</lat>
|
||||
</location>
|
||||
</client>
|
||||
|
||||
<!-- This is all stuff that relates to the orientation and dimensions of the client -->
|
||||
<!-- So that we know how to re-map the 0.0-1.0 coordinates that come in for each point -->
|
||||
<!-- Also for figuring out the down vector for devices with accelerometers and how that effects drips -->
|
||||
<!-- All numbers should be between 0.0 - 1.0 -->
|
||||
<environment>
|
||||
<offset>
|
||||
<x>0.0</x>
|
||||
<y>0.0</y>
|
||||
<z>0.0</z>
|
||||
</offset>
|
||||
<rotation>
|
||||
<x>0.0</x>
|
||||
<y>0.0</y>
|
||||
<z>0.0</z>
|
||||
</rotation>
|
||||
<up>
|
||||
<x>0.0</x> <!-- commonly up for iphone apps -->
|
||||
<y>-1.0</y> <!-- most common -->
|
||||
<z>0.0</z>
|
||||
</up>
|
||||
<screenbounds> <!-- use this as your multipler to get 0.0 to 1.0 back to right size - pts should never go off 0.0 to 1.0 -->
|
||||
<x>1024</x>
|
||||
<y>768</y>
|
||||
<z>0</z>
|
||||
</screenbounds>
|
||||
<origin>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<z>0</z>
|
||||
</origin>
|
||||
<realscale> <!-- how these units relate to real world units - good for laser tag -->
|
||||
<x>1000</x>
|
||||
<y>600</y>
|
||||
<z>0</z>
|
||||
<unit>cm</unit>
|
||||
</realscale>
|
||||
<audio>youraudio.mp3</audio> <!-- path to audio file -->
|
||||
<background>yourimage.jpg</background> <!-- path to image file -->
|
||||
</environment>
|
||||
|
||||
</header>
|
||||
|
||||
<drawing>
|
||||
<!-- for all stroke and movement stuff it helps to have everything inside the stroke tag -->
|
||||
<!-- this way it is easy to get a sense of order to events -->
|
||||
|
||||
<stroke isdrawing="false"> <!-- for non drawing mouse movements -->
|
||||
<pt>
|
||||
<x>0.0</x>
|
||||
<y>0.0</y>
|
||||
<z>0.0</z> <!--this is optional -->
|
||||
<t>0.013</t> <!-- time is optional too -->
|
||||
<!-- NOTE: older versions of GML use <time> instead of <t> -->
|
||||
</pt>
|
||||
</stroke>
|
||||
|
||||
<stroke> <!-- by default stroke drawing is true -->
|
||||
|
||||
<!-- each stroke could be drawn with a different brush -->
|
||||
<!-- if no brush tag is found for a stroke then it inherits the previous settings -->
|
||||
<brush>
|
||||
<mode>0</mode> <!-- same as uniqueStyleID but an internal reference -->
|
||||
<uniquestyleid>LaserTagArrowLetters</uniquestyleid> <!-- unique blackbook string for your style -->
|
||||
<!-- see note about spec at the bottom - like unique style but with extra info -->
|
||||
<spec>http://aurltodescribethebrushspec.com/someSpec.xml</spec>
|
||||
<width>10</width>
|
||||
<speedtowidthratio>1.5</speedtowidthratio> <!-- put 0 for fixed width -->
|
||||
<dripamnt>1.0</dripamnt>
|
||||
<dripspeed>1.0</dripspeed>
|
||||
<layerabsolute>0</layerabsolute> <!--Think photoshop layers-->
|
||||
<color>
|
||||
<r>255</r>
|
||||
<g>255</g>
|
||||
<b>255</b>
|
||||
<a>255</a> <!-- optional -->
|
||||
</color>
|
||||
<dripvecrelativetoup> <!-- what angle do our drips go in relation to our up vector -->
|
||||
<x>0</x>
|
||||
<y>1</y>
|
||||
<z>0</z>
|
||||
</dripvecrelativetoup>
|
||||
</brush>
|
||||
|
||||
<pt>
|
||||
<x>0.0</x>
|
||||
<y>0.0</y>
|
||||
<z>0.0</z> <!--this is optional -->
|
||||
<t>0.013</t> <!-- time is optional too -->
|
||||
</pt>
|
||||
|
||||
<pt>
|
||||
<x>0.0</x>
|
||||
<y>0.0</y>
|
||||
<z>0.0</z> <!--this is optional -->
|
||||
<t>0.023</t> <!-- time is optional too -->
|
||||
</pt>
|
||||
|
||||
|
||||
</stroke>
|
||||
|
||||
<!-- this stroke inherits the previous stroke properties -->
|
||||
<!-- but changes color and draws on the layer below -->
|
||||
<stroke>
|
||||
<info> <!-- optional info - more stuff soon-->
|
||||
<curved>true</curved>
|
||||
</info>
|
||||
<brush>
|
||||
<color>
|
||||
<r>255</r>
|
||||
<g>255</g>
|
||||
<b>0</b>
|
||||
</color>
|
||||
<layerrelative> <!-- this means one layer bellow the previous layer -->
|
||||
-1
|
||||
</layerrelative>
|
||||
</brush>
|
||||
|
||||
<pt>
|
||||
<x>0.0</x>
|
||||
<y>0.0</y>
|
||||
</pt>
|
||||
|
||||
<pt>
|
||||
<x>0.0</x>
|
||||
<y>0.0</y>
|
||||
</pt>
|
||||
|
||||
</stroke>
|
||||
|
||||
<stroke>
|
||||
<pt>
|
||||
<pres>0.5</pres> <!-- Optional. Preasure range from 0 to 1 -->
|
||||
<rot>0.5</rot> <!-- Optional. Rotation range from 0 to 1 for 0 to 2*PI -->
|
||||
<dir> <!-- Optional Direction -->
|
||||
<x></x> <!-- range from 0 to 1 -->
|
||||
<y></y> <!-- range from 0 to 1 -->
|
||||
<z></z> <!-- Optional inside direction. Range from 0 to 1 -->
|
||||
</dir>
|
||||
</pt>
|
||||
</stroke>
|
||||
</drawing>
|
||||
|
||||
</tag>
|
||||
|
||||
</gml>
|
||||
'''
|
||||
126
clitools/generators/fromOSC.py
Normal file
126
clitools/generators/fromOSC.py
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# -*- mode: Python -*-
|
||||
|
||||
'''
|
||||
Forward /pl pointlist to cli
|
||||
|
||||
input OSC in END points format : (x,y,color)
|
||||
output CLI in CLI points format : [x,y,color]
|
||||
|
||||
/pl "[(150.0, 230.0, 255), (170.0, 170.0, 255), (230.0, 170.0, 255), (210.0, 230.0, 255), (150.0, 230.0, 255)]"
|
||||
|
||||
v0.1.0
|
||||
|
||||
LICENCE : CC
|
||||
|
||||
by Cocoa, Sam Neurohack
|
||||
|
||||
'''
|
||||
from __future__ import print_function
|
||||
from OSC3 import OSCServer, OSCClient, OSCMessage
|
||||
import sys
|
||||
from time import sleep
|
||||
import argparse
|
||||
import ast
|
||||
|
||||
argsparser = argparse.ArgumentParser(description="fromOSC generator")
|
||||
argsparser.add_argument("-i","--ip",help="IP to bind to (0.0.0.0 by default)",default="0.0.0.0",type=str)
|
||||
argsparser.add_argument("-p","--port",help="OSC port to bind to (9002 by default)",default=9002,type=str)
|
||||
argsparser.add_argument("-v","--verbose",action="store_true",help="Verbose output")
|
||||
args = argsparser.parse_args()
|
||||
|
||||
verbose = args.verbose
|
||||
ip = args.ip
|
||||
port = int(args.port)
|
||||
|
||||
def debug(*args, **kwargs):
|
||||
if( verbose == False ):
|
||||
return
|
||||
print(*args, file=sys.stderr, **kwargs)
|
||||
|
||||
oscserver = OSCServer( (ip, port) )
|
||||
oscserver.timeout = 0
|
||||
run = True
|
||||
|
||||
# this method of reporting timeouts only works by convention
|
||||
# that before calling handle_request() field .timed_out is
|
||||
# set to False
|
||||
def handle_timeout(self):
|
||||
self.timed_out = True
|
||||
|
||||
# funny python's way to add a method to an instance of a class
|
||||
import types
|
||||
oscserver.handle_timeout = types.MethodType(handle_timeout, oscserver)
|
||||
|
||||
# RAW OSC Frame available ?
|
||||
def OSC_frame():
|
||||
# clear timed_out flag
|
||||
oscserver.timed_out = False
|
||||
# handle all pending requests then return
|
||||
while not oscserver.timed_out:
|
||||
oscserver.handle_request()
|
||||
|
||||
|
||||
# default handler
|
||||
def OSChandler(oscpath, tags, args, source):
|
||||
|
||||
oscaddress = ''.join(oscpath.split("/"))
|
||||
debug("fromOSC Default OSC Handler got oscpath", oscpath, "from" + str(source[0]), ":", args)
|
||||
#print("OSC address", path)
|
||||
#print("find.. /bhoreal ?", path.find('/bhoreal'))
|
||||
|
||||
if oscpath == "/pl" and len(args)==1:
|
||||
|
||||
debug("correct OSC type :'/pl")
|
||||
|
||||
if validate(args[0]) == True:
|
||||
|
||||
debug("new pl : ", args[0])
|
||||
line = args[0].replace("(",'[')
|
||||
line = line.replace(")",']')
|
||||
line = "[{}]".format(line)
|
||||
print(line, flush=True);
|
||||
|
||||
else:
|
||||
debug("Bad pointlist -> msg trapped.")
|
||||
|
||||
else:
|
||||
debug("BAD OSC Message : " + oscpath +" " +args[0])
|
||||
|
||||
|
||||
oscserver.addMsgHandler( "default", OSChandler )
|
||||
|
||||
|
||||
def validate(pointlist):
|
||||
|
||||
state = True
|
||||
|
||||
if len(pointlist)<9:
|
||||
debug("Not enough characters :", pointlist)
|
||||
state = False
|
||||
|
||||
if pointlist.find("(") == -1:
|
||||
debug("Bad format : use () not [] for points", pointlist)
|
||||
state = False
|
||||
|
||||
try:
|
||||
pl = bytes(pointlist, 'ascii')
|
||||
check = ast.literal_eval(pl.decode('ascii'))
|
||||
|
||||
except:
|
||||
debug("BAD POINTLIST :", pointlist)
|
||||
state = False
|
||||
|
||||
return state
|
||||
|
||||
|
||||
# simulate a "game engine"
|
||||
while run:
|
||||
# do the game stuff:
|
||||
sleep(0.01)
|
||||
# call user script
|
||||
OSC_frame()
|
||||
|
||||
oscserver.close()
|
||||
|
||||
72
clitools/generators/fromRedis.py
Executable file
72
clitools/generators/fromRedis.py
Executable file
|
|
@ -0,0 +1,72 @@
|
|||
#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# -*- mode: Python -*-
|
||||
|
||||
|
||||
'''
|
||||
|
||||
This generator reads a frame from redis
|
||||
v0.1.0
|
||||
|
||||
Use it to create feedback loops by writing to the same frame
|
||||
or to copy the frame from someone else
|
||||
|
||||
LICENCE : CC
|
||||
|
||||
by cocoa
|
||||
|
||||
'''
|
||||
|
||||
from __future__ import print_function
|
||||
import ast
|
||||
import argparse
|
||||
import json
|
||||
import redis
|
||||
import sys
|
||||
import time
|
||||
name="generator::fromRedis"
|
||||
|
||||
|
||||
def debug(*args, **kwargs):
|
||||
if( verbose == False ):
|
||||
return
|
||||
print(*args, file=sys.stderr, **kwargs)
|
||||
|
||||
|
||||
argsparser = argparse.ArgumentParser(description="Dummy generator")
|
||||
argsparser.add_argument("-k","--key",required=True,help="Redis key to look after",default=30,type=str)
|
||||
argsparser.add_argument("-i","--ip",help="IP address of the Redis server ",default="127.0.0.1",type=str)
|
||||
argsparser.add_argument("-p","--port",help="Port of the Redis server ",default="6379",type=str)
|
||||
argsparser.add_argument("-f","--fps",help="Frame Per Second",default=30,type=int)
|
||||
argsparser.add_argument("-v","--verbose",action="store_true",help="Verbose output")
|
||||
args = argsparser.parse_args()
|
||||
|
||||
fps = args.fps
|
||||
verbose = args.verbose
|
||||
key = args.key
|
||||
ip = args.ip
|
||||
port = args.port
|
||||
optimal_looptime = 1 / fps
|
||||
debug(name+" optimal looptime "+str(optimal_looptime))
|
||||
|
||||
r = redis.Redis(
|
||||
host=ip,
|
||||
port=port)
|
||||
|
||||
while True:
|
||||
start = time.time()
|
||||
# Read from Redis
|
||||
line = r.get(key)
|
||||
# Decode as list of tuples
|
||||
pointsList = ast.literal_eval(line.decode('ascii'))
|
||||
# convert to list of lists
|
||||
pointsList = [list(elem) for elem in pointsList]
|
||||
# Convert to JSON string
|
||||
line = json.dumps( pointsList )
|
||||
debug(name,"Key:{} line:{}".format(key,line))
|
||||
print(line, flush=True);
|
||||
looptime = time.time() - start
|
||||
if( looptime < optimal_looptime ):
|
||||
time.sleep( optimal_looptime - looptime)
|
||||
debug(name+" micro sleep:"+str( optimal_looptime - looptime))
|
||||
|
||||
84
clitools/generators/fromUDP.py
Normal file
84
clitools/generators/fromUDP.py
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# -*- mode: Python -*-
|
||||
|
||||
'''
|
||||
|
||||
fromUDP
|
||||
|
||||
Udp server to cli
|
||||
v0.1b
|
||||
|
||||
'''
|
||||
from __future__ import print_function
|
||||
import traceback, time
|
||||
import argparse
|
||||
import socket
|
||||
import _thread
|
||||
import sys
|
||||
|
||||
name="generator::fromUDP"
|
||||
|
||||
|
||||
def debug(*args, **kwargs):
|
||||
if( verbose == False ):
|
||||
return
|
||||
print(*args, file=sys.stderr, **kwargs)
|
||||
|
||||
|
||||
argsparser = argparse.ArgumentParser(description="fromUDP v0.1b help mode")
|
||||
argsparser.add_argument("-v","--verbose",action="store_true",help="Verbose output")
|
||||
argsparser.add_argument("-i","--ip",help="IP to bind to (0.0.0.0 by default)",default="0.0.0.0",type=str)
|
||||
argsparser.add_argument("-p","--port",help="UDP port to bind to (9000 by default)",default=9000,type=str)
|
||||
args = argsparser.parse_args()
|
||||
|
||||
verbose = args.verbose
|
||||
ip = args.ip
|
||||
port = int(args.port)
|
||||
verbose = args.verbose
|
||||
|
||||
|
||||
|
||||
def udp_thread():
|
||||
|
||||
while True:
|
||||
|
||||
payload, client_address = sock.recvfrom(1024)
|
||||
udpath = payload.decode('utf_8')
|
||||
debug(udpath[0:])
|
||||
print(udpath[0:], flush=True);
|
||||
|
||||
'''
|
||||
# Reply to client
|
||||
bytesToSend = str.encode("ACK :"+str(payload))
|
||||
serverAddressPort = (client_address, port)
|
||||
bufferSize = 1024
|
||||
#sock.sendto(bytesToSend, serverAddressPort)
|
||||
sock.sendto(bytesToSend, client_address)
|
||||
'''
|
||||
|
||||
def StartUDP(serverIP, UDPORT):
|
||||
global sock
|
||||
|
||||
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
server = ( serverIP,UDPORT)
|
||||
sock.bind(server)
|
||||
_thread.start_new_thread(udp_thread, ())
|
||||
|
||||
|
||||
StartUDP(ip, port)
|
||||
|
||||
|
||||
# Do something else
|
||||
try:
|
||||
|
||||
while True:
|
||||
time.sleep(0.005)
|
||||
|
||||
except Exception:
|
||||
traceback.print_exc()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
319
clitools/generators/fromilda.py
Normal file
319
clitools/generators/fromilda.py
Normal file
|
|
@ -0,0 +1,319 @@
|
|||
#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# -*- mode: Python -*-
|
||||
|
||||
'''
|
||||
|
||||
fromild
|
||||
v0.1.0
|
||||
|
||||
Read/display once an .ild animation file and quit ??
|
||||
LICENCE : CC
|
||||
|
||||
by cocoa and Sam Neurohack
|
||||
|
||||
Heavy u-se of :
|
||||
|
||||
ILDA.py
|
||||
|
||||
Python module for dealing with the ILDA Image Data Transfer Format,
|
||||
an interchange format for laser image frames.
|
||||
|
||||
Copyright (c) 2008 Micah Dowty
|
||||
|
||||
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.
|
||||
|
||||
'''
|
||||
|
||||
from __future__ import print_function
|
||||
import time
|
||||
import struct
|
||||
import argparse
|
||||
import sys
|
||||
|
||||
name="generator::fromild"
|
||||
|
||||
|
||||
def debug(*args, **kwargs):
|
||||
if( verbose == False ):
|
||||
return
|
||||
print(*args, file=sys.stderr, **kwargs)
|
||||
|
||||
argsparser = argparse.ArgumentParser(description=".ild file frame generator")
|
||||
argsparser.add_argument("-f","--fps",help="Frame Per Second",default=30,type=int)
|
||||
argsparser.add_argument("-v","--verbose",action="store_true",help="Verbose output")
|
||||
argsparser.add_argument("-i","--ild",help=".ild file",default="book2.ild",type=str)
|
||||
args = argsparser.parse_args()
|
||||
|
||||
fps=args.fps
|
||||
verbose=args.verbose
|
||||
|
||||
optimal_looptime = 1 / fps
|
||||
debug(name+" optimal looptime "+str(optimal_looptime))
|
||||
|
||||
# Format codes
|
||||
FORMAT_3D = 0
|
||||
FORMAT_2D = 1
|
||||
FORMAT_COLOR_TABLE = 2
|
||||
|
||||
# Mapping from FORMAT_* codes to struct format strings
|
||||
formatTable = (
|
||||
'>hhhH',
|
||||
'>hhH',
|
||||
'>BBB',
|
||||
)
|
||||
|
||||
# Header values
|
||||
HEADER_MAGIC = b"ILDA\0\0\0"
|
||||
HEADER_RESERVED = 0
|
||||
HEADER_FORMAT = ">7sB16sHHHBB"
|
||||
HEADER_LEN = struct.calcsize(HEADER_FORMAT)
|
||||
|
||||
# 64 default colors table : use rgb2int(colors64[ildacolor])
|
||||
colors64 = [[255, 0, 0], [255, 17, 0], [255, 34, 0], [255, 51, 0], [255, 68, 0], [255, 85, 0], [255, 102, 0], [255, 119, 0], [255, 136, 0], [255, 153, 0], [255, 170, 0], [255, 187, 0], [255, 204, 0], [255, 221, 0], [255, 238, 0], [255, 255, 0], [255, 255, 0], [238, 255, 0], [204, 255, 0], [170, 255, 0], [136, 255, 0], [102, 255, 0], [68, 255, 0], [34, 255, 0], [0, 255, 0], [0, 255, 34], [0, 255, 68], [0, 255, 102], [0, 255, 136], [0, 255, 170], [0, 255, 204], [0, 255, 238], [0, 136, 255], [0, 119, 255], [0, 102, 255], [0, 102, 255], [0, 85, 255], [0, 68, 255], [0, 68, 255], [0, 34, 255], [0, 0, 255], [34, 0, 255], [68, 0, 255], [102, 0, 255], [136, 0, 255], [170, 0, 255], [204, 0, 255], [238, 0, 255], [255, 0, 255], [255, 34, 255], [255, 68, 255], [255, 102, 255], [255, 136, 255], [255, 170, 255], [255, 204, 255], [255, 238, 255], [255, 255, 255], [255, 238, 238], [255, 204, 204], [255, 170, 170], [255, 136, 136], [255, 102, 102], [255, 68, 68], [0, 34, 34]]
|
||||
|
||||
|
||||
# 256 default colors table
|
||||
colors256 = [[0, 0, 0], [255, 255, 255], [255, 0, 0], [255, 255, 0], [0, 255, 0], [0, 255, 255], [0, 0, 255], [255, 0, 255], [255, 128, 128], [255, 140, 128], [255, 151, 128], [255, 163, 128], [255, 174, 128], [255, 186, 128], [255, 197, 128], [255, 209, 128], [255, 220, 128], [255, 232, 128], [255, 243, 128], [255, 255, 128], [243, 255, 128], [232, 255, 128], [220, 255, 128], [209, 255, 128], [197, 255, 128], [186, 255, 128], [174, 255, 128], [163, 255, 128], [151, 255, 128], [140, 255, 128], [128, 255, 128], [128, 255, 140], [128, 255, 151], [128, 255, 163], [128, 255, 174], [128, 255, 186], [128, 255, 197], [128, 255, 209], [128, 255, 220], [128, 255, 232], [128, 255, 243], [128, 255, 255], [128, 243, 255], [128, 232, 255], [128, 220, 255], [128, 209, 255], [128, 197, 255], [128, 186, 255], [128, 174, 255], [128, 163, 255], [128, 151, 255], [128, 140, 255], [128, 128, 255], [140, 128, 255], [151, 128, 255], [163, 128, 255], [174, 128, 255], [186, 128, 255], [197, 128, 255], [209, 128, 255], [220, 128, 255], [232, 128, 255], [243, 128, 255], [255, 128, 255], [255, 128, 243], [255, 128, 232], [255, 128, 220], [255, 128, 209], [255, 128, 197], [255, 128, 186], [255, 128, 174], [255, 128, 163], [255, 128, 151], [255, 128, 140], [255, 0, 0], [255, 23, 0], [255, 46, 0], [255, 70, 0], [255, 93, 0], [255, 116, 0], [255, 139, 0], [255, 162, 0], [255, 185, 0], [255, 209, 0], [255, 232, 0], [255, 255, 0], [232, 255, 0], [209, 255, 0], [185, 255, 0], [162, 255, 0], [139, 255, 0], [116, 255, 0], [93, 255, 0], [70, 255, 0], [46, 255, 0], [23, 255, 0], [0, 255, 0], [0, 255, 23], [0, 255, 46], [0, 255, 70], [0, 255, 93], [0, 255, 116], [0, 255, 139], [0, 255, 162], [0, 255, 185], [0, 255, 209], [0, 255, 232], [0, 255, 255], [0, 232, 255], [0, 209, 255], [0, 185, 255], [0, 162, 255], [0, 139, 255], [0, 116, 255], [0, 93, 255], [0, 70, 255], [0, 46, 255], [0, 23, 255], [0, 0, 255], [23, 0, 255], [46, 0, 255], [70, 0, 255], [93, 0, 255], [116, 0, 255], [139, 0, 255], [162, 0, 255], [185, 0, 255], [209, 0, 255], [232, 0, 255], [255, 0, 255], [255, 0, 232], [255, 0, 209], [255, 0, 185], [255, 0, 162], [255, 0, 139], [255, 0, 116], [255, 0, 93], [255, 0, 70], [255, 0, 46], [255, 0, 23], [128, 0, 0], [128, 12, 0], [128, 23, 0], [128, 35, 0], [128, 47, 0], [128, 58, 0], [128, 70, 0], [128, 81, 0], [128, 93, 0], [128, 105, 0], [128, 116, 0], [128, 128, 0], [116, 128, 0], [105, 128, 0], [93, 128, 0], [81, 128, 0], [70, 128, 0], [58, 128, 0], [47, 128, 0], [35, 128, 0], [23, 128, 0], [12, 128, 0], [0, 128, 0], [0, 128, 12], [0, 128, 23], [0, 128, 35], [0, 128, 47], [0, 128, 58], [0, 128, 70], [0, 128, 81], [0, 128, 93], [0, 128, 105], [0, 128, 116], [0, 128, 128], [0, 116, 128], [0, 105, 128], [0, 93, 128], [0, 81, 128], [0, 70, 128], [0, 58, 128], [0, 47, 128], [0, 35, 128], [0, 23, 128], [0, 12, 128], [0, 0, 128], [12, 0, 128], [23, 0, 128], [35, 0, 128], [47, 0, 128], [58, 0, 128], [70, 0, 128], [81, 0, 128], [93, 0, 128], [105, 0, 128], [116, 0, 128], [128, 0, 128], [128, 0, 116], [128, 0, 105], [128, 0, 93], [128, 0, 81], [128, 0, 70], [128, 0, 58], [128, 0, 47], [128, 0, 35], [128, 0, 23], [128, 0, 12], [255, 192, 192], [255, 64, 64], [192, 0, 0], [64, 0, 0], [255, 255, 192], [255, 255, 64], [192, 192, 0], [64, 64, 0], [192, 255, 192], [64, 255, 64], [0, 192, 0], [0, 64, 0], [192, 255, 255], [64, 255, 255], [0, 192, 192], [0, 64, 64], [192, 192, 255], [64, 64, 255], [0, 0, 192], [0, 0, 64], [255, 192, 255], [255, 64, 255], [192, 0, 192], [64, 0, 64], [255, 96, 96], [255, 255, 255], [245, 245, 245], [235, 235, 235], [224, 224, 224], [213, 213, 213], [203, 203, 203], [192, 192, 192], [181, 181, 181], [171, 171, 171], [160, 160, 160], [149, 149, 149], [139, 139, 139], [128, 128, 128], [117, 117, 117], [107, 107, 107], [96, 96, 96], [85, 85, 85], [75, 75, 75], [64, 64, 64], [53, 53, 53], [43, 43, 43], [32, 32, 32], [21, 21, 21], [11, 11, 11], [0, 0, 0]]
|
||||
|
||||
def rgb2int(rgb):
|
||||
return int('0x%02x%02x%02x' % tuple(rgb),0)
|
||||
|
||||
class Table(object):
|
||||
"""Container object for one ILDA table: either a frame (table of points)
|
||||
or a palette (table of colors).
|
||||
|
||||
The 'items' list contains the data within this table. Each item
|
||||
is a tuple, corresponding to the raw values within that row of the
|
||||
table.
|
||||
|
||||
2D frame: (x, y, status)
|
||||
3D frame: (x, y, z, status)
|
||||
Color: (r, g, b)
|
||||
|
||||
"""
|
||||
def __init__(self, format=FORMAT_2D, name="",
|
||||
length=0, number=0, total=0, scanHead=0):
|
||||
self.__dict__.update(locals())
|
||||
self.items = []
|
||||
self.itemsproducer = None
|
||||
|
||||
def __repr__(self):
|
||||
return ("<ILDA.Table format=%d name=%r "
|
||||
"length=%d number=%d total=%d scanHead=%d>" %
|
||||
(self.format, self.name, self.length, self.number,
|
||||
self.total, self.scanHead))
|
||||
|
||||
def unpackHeader(self, data):
|
||||
magic, self.format, self.name, self.length, \
|
||||
self.number, self.total, self.scanHead, \
|
||||
reserved = struct.unpack(HEADER_FORMAT, data)
|
||||
print(magic, HEADER_MAGIC)
|
||||
if magic != HEADER_MAGIC:
|
||||
raise ValueError("Bad ILDA header magic. Not an ILDA file?")
|
||||
if reserved != HEADER_RESERVED:
|
||||
raise ValueError("Reserved ILDA field is not zero.")
|
||||
|
||||
def packHeader(self):
|
||||
return struct.pack(HEADER_FORMAT, HEADER_MAGIC, self.format,
|
||||
self.name, self.length, self.number,
|
||||
self.total, self.scanHead, HEADER_RESERVED)
|
||||
|
||||
def readHeader(self, stream):
|
||||
self.unpackHeader(stream.read(HEADER_LEN))
|
||||
|
||||
def writeHeader(self, stream):
|
||||
stream.write(self.packHeader())
|
||||
|
||||
def _getItemFormat(self):
|
||||
try:
|
||||
return formatTable[self.format]
|
||||
except IndexError:
|
||||
raise ValueError("Unsupported format code")
|
||||
|
||||
def read_stream(self, stream):
|
||||
"""Read the header, then read all items in this table."""
|
||||
self.readHeader(stream)
|
||||
if self.length:
|
||||
fmt = self._getItemFormat()
|
||||
itemSize = struct.calcsize(fmt)
|
||||
self.items = [struct.unpack(fmt, stream.read(itemSize))
|
||||
for i in range(self.length)]
|
||||
self.itemsproducer = self.produce()
|
||||
|
||||
def write(self, stream):
|
||||
"""Write the header, then write all items in this table."""
|
||||
self.writeHeader(stream)
|
||||
if self.length:
|
||||
fmt = self._getItemFormat()
|
||||
itemSize = struct.calcsize(fmt)
|
||||
stream.write(''.join([struct.pack(fmt, *item)
|
||||
for item in self.items]))
|
||||
|
||||
def iterPoints(self):
|
||||
"""Iterate over Point instances for each item in this table.
|
||||
Only makes sense if this is a 2D or 3D point table.
|
||||
"""
|
||||
for item in self.items:
|
||||
p = Point()
|
||||
p.decode(item)
|
||||
yield p
|
||||
|
||||
|
||||
def produce(self):
|
||||
"""Iterate over Point instances for each item in this table.
|
||||
Only makes sense if this is a 2D or 3D point table.
|
||||
"""
|
||||
while True:
|
||||
for item in self.items:
|
||||
p = Point()
|
||||
p.decode(item)
|
||||
yield p.encode()
|
||||
#yield (p.x, p.y, p.z, p.color, p.blanking)
|
||||
|
||||
def read(self, cap):
|
||||
"""yields what dac.play_stream() needs (x, y, z, ?, ?)
|
||||
"""
|
||||
return [next(self.itemsproducer) for i in range(cap)]
|
||||
|
||||
|
||||
class Point:
|
||||
"""Abstraction for one vector point. The Table object, for
|
||||
completeness and efficiency, stores raw tuples for each
|
||||
point. This is a higher level interface that decodes the status
|
||||
bits and represents coordinates in floating point.
|
||||
"""
|
||||
def __init__(self, x=0.0, y=0.0, z=0.0, color=0, blanking=False):
|
||||
self.__dict__.update(locals())
|
||||
|
||||
def __repr__(self):
|
||||
|
||||
return "%s, %s, %s, %s, %s" % (
|
||||
self.x, self.y, self.z, self.color, self.blanking)
|
||||
#return "<ILDA.Point (%s, %s, %s) color=%s blanking=%s>" % (
|
||||
# self.x, self.y, self.z, self.color, self.blanking)
|
||||
|
||||
def encode(self):
|
||||
status = self.color & 0xFF
|
||||
if self.blanking:
|
||||
status |= 1 << 14
|
||||
|
||||
return (
|
||||
int( min(0x7FFF, max(-0x7FFF, self.x * 0x7FFF)) ),
|
||||
int( min(0x7FFF, max(-0x7FFF, self.y * 0x7FFF)) ),
|
||||
int( min(0x7FFF, max(-0x7FFF, self.z * 0x7FFF)) ),
|
||||
int( min(0x7FFF, max(-0x7FFF, self.color * 0x7FFF)) ),
|
||||
int( min(0x7FFF, max(-0x7FFF, self.blanking * 0x7FFF)) )
|
||||
)
|
||||
|
||||
def decode(self, t):
|
||||
#print "~~ Decoding, t of len "+ str(len(t)) +" is: " + str(t)
|
||||
self.x = t[0] / 0x7FFF
|
||||
self.y = t[1] / 0x7FFF
|
||||
if len(t) > 3:
|
||||
self.z = t[2] / 0x7FFF
|
||||
# self.color = t[3] & 0xFF
|
||||
# self.blanking = (t[3] & (1 << 14)) != 0
|
||||
else:
|
||||
self.z = 0.0
|
||||
|
||||
self.color = t[-1] & 0xFF
|
||||
self.blanking = (t[-1] & (1 << 14)) != 0
|
||||
|
||||
|
||||
def read(stream):
|
||||
"""Read ILDA data from a stream until we hit the
|
||||
end-of-stream marker. Yields a sequence of Table objects.
|
||||
"""
|
||||
while True:
|
||||
t = Table()
|
||||
t.read_stream(stream)
|
||||
if not t.length:
|
||||
# End-of-stream
|
||||
break
|
||||
yield t
|
||||
|
||||
|
||||
def write(stream, tables):
|
||||
"""Write a sequence of tables in ILDA format,
|
||||
terminated by an end-of-stream marker.
|
||||
"""
|
||||
for t in tables:
|
||||
t.write(stream)
|
||||
Table().write(stream)
|
||||
|
||||
|
||||
def readFrames(stream):
|
||||
"""Read ILDA data from a stream, and ignore
|
||||
all non-frame tables. Yields only 2D or 3D
|
||||
point tables.
|
||||
"""
|
||||
for t in read(stream):
|
||||
if t.format in (FORMAT_2D, FORMAT_3D):
|
||||
yield t
|
||||
|
||||
|
||||
def readFirstFrame(stream):
|
||||
"""Read only a single frame from an ILDA stream."""
|
||||
for frame in readFrames(stream):
|
||||
return frame
|
||||
|
||||
|
||||
#
|
||||
f = open(args.ild, 'rb')
|
||||
myframe = readFirstFrame(f)
|
||||
|
||||
while myframe.number +1< myframe.total:
|
||||
|
||||
start = time.time()
|
||||
shape =[]
|
||||
|
||||
if myframe is None:
|
||||
f.close()
|
||||
break
|
||||
|
||||
debug(name,"Frame", myframe.number, "/",myframe.total, "length", myframe.length)
|
||||
|
||||
for p in myframe.iterPoints():
|
||||
p2 = str(p)
|
||||
point = p2.split(',')
|
||||
|
||||
x = float(point[0])
|
||||
y = float(point[1])
|
||||
z = float(point[2])
|
||||
color = int(point[3])
|
||||
blanking = point[4][1:]
|
||||
|
||||
if blanking == "True":
|
||||
shape.append([300+(x*300),300+(-y*300),0])
|
||||
else:
|
||||
shape.append([300+(x*300),300+(-y*300),rgb2int(colors64[color])])
|
||||
|
||||
print(shape, flush=True);
|
||||
myframe = readFirstFrame(f)
|
||||
|
||||
looptime = time.time() - start
|
||||
if( looptime < optimal_looptime ):
|
||||
time.sleep( optimal_looptime - looptime)
|
||||
debug(name+" micro sleep:"+str( optimal_looptime - looptime))
|
||||
|
||||
f.close()
|
||||
debug(name + " end of .ild animation")
|
||||
131
clitools/generators/osc2redis.py
Normal file
131
clitools/generators/osc2redis.py
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# -*- mode: Python -*-
|
||||
|
||||
'''
|
||||
|
||||
Forward pointlist to redis key
|
||||
|
||||
END POINT Format : (x,y,color)
|
||||
|
||||
/pl/0/0 "[(150.0, 230.0, 255), (170.0, 170.0, 255), (230.0, 170.0, 255), (210.0, 230.0, 255), (150.0, 230.0, 255)]"
|
||||
|
||||
v0.1.0
|
||||
|
||||
LICENCE : CC
|
||||
|
||||
by Cocoa, Sam Neurohack
|
||||
|
||||
'''
|
||||
|
||||
from OSC3 import OSCServer, OSCClient, OSCMessage
|
||||
import sys
|
||||
from time import sleep
|
||||
import argparse
|
||||
import ast
|
||||
import redis
|
||||
|
||||
argsparser = argparse.ArgumentParser(description="osc2redis generator")
|
||||
argsparser.add_argument("-i","--ip",help="IP to bind to (0.0.0.0 by default)",default="0.0.0.0",type=str)
|
||||
argsparser.add_argument("-p","--port",help="OSC port to bind to (9002 by default)",default=9002,type=str)
|
||||
|
||||
argsparser.add_argument("-r","--rip",help="Redis server IP (127.0.0.1 by default)",default="127.0.0.1",type=str)
|
||||
argsparser.add_argument("-o","--rout",help="Redis port (6379 by default)",default=6379,type=str)
|
||||
argsparser.add_argument("-v","--verbose",action="store_true",help="Verbose output")
|
||||
args = argsparser.parse_args()
|
||||
|
||||
verbose = args.verbose
|
||||
ip = args.ip
|
||||
port = int(args.port)
|
||||
rip = args.rip
|
||||
rport = int(args.rout)
|
||||
|
||||
|
||||
r = redis.StrictRedis(host=rip, port=rport, db=0)
|
||||
|
||||
|
||||
def debug(msg):
|
||||
if( verbose == False ):
|
||||
return
|
||||
print(msg)
|
||||
|
||||
|
||||
oscserver = OSCServer( (ip, port) )
|
||||
oscserver.timeout = 0
|
||||
run = True
|
||||
|
||||
# this method of reporting timeouts only works by convention
|
||||
# that before calling handle_request() field .timed_out is
|
||||
# set to False
|
||||
def handle_timeout(self):
|
||||
self.timed_out = True
|
||||
|
||||
# funny python's way to add a method to an instance of a class
|
||||
import types
|
||||
oscserver.handle_timeout = types.MethodType(handle_timeout, oscserver)
|
||||
|
||||
|
||||
def validate(pointlist):
|
||||
|
||||
state = True
|
||||
|
||||
if len(pointlist)<9:
|
||||
state = False
|
||||
|
||||
try:
|
||||
pl = bytes(pointlist, 'ascii')
|
||||
check = ast.literal_eval(pl.decode('ascii'))
|
||||
|
||||
except:
|
||||
state = False
|
||||
|
||||
return state
|
||||
|
||||
|
||||
# RAW OSC Frame available ?
|
||||
def OSC_frame():
|
||||
# clear timed_out flag
|
||||
oscserver.timed_out = False
|
||||
# handle all pending requests then return
|
||||
while not oscserver.timed_out:
|
||||
oscserver.handle_request()
|
||||
|
||||
|
||||
# default handler
|
||||
def OSChandler(oscpath, tags, args, source):
|
||||
|
||||
oscaddress = ''.join(oscpath.split("/"))
|
||||
print("fromOSC Default OSC Handler got oscpath :", oscpath, "from :" + str(source[0]), "args :", args)
|
||||
print(oscpath.find("/pl/"), len(oscpath))
|
||||
|
||||
if oscpath.find("/pl/") ==0 and len(args)==1:
|
||||
|
||||
print("correct OSC type :'/pl/")
|
||||
|
||||
if validate(args[0]) == True and len(oscpath) == 7:
|
||||
print("new pl for key ", oscpath, ":", args[0])
|
||||
|
||||
if r.set(oscpath,args[0])==True:
|
||||
debug("exports::redis set("+str(oscpath)+") to "+args[0])
|
||||
|
||||
else:
|
||||
print("Bad pointlist -> msg trapped.")
|
||||
|
||||
|
||||
else:
|
||||
print("BAD OSC Message :", oscpath)
|
||||
|
||||
oscserver.addMsgHandler( "default", OSChandler )
|
||||
|
||||
|
||||
|
||||
|
||||
# simulate a "game engine"
|
||||
while run:
|
||||
# do the game stuff:
|
||||
sleep(0.01)
|
||||
# call user script
|
||||
OSC_frame()
|
||||
|
||||
oscserver.close()
|
||||
|
||||
174
clitools/generators/redilysis_lines.py
Executable file
174
clitools/generators/redilysis_lines.py
Executable file
|
|
@ -0,0 +1,174 @@
|
|||
#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# -*- mode: Python -*-
|
||||
|
||||
|
||||
'''
|
||||
|
||||
redilysis_lines
|
||||
v0.1.0
|
||||
|
||||
Add a line on every frame and scroll
|
||||
|
||||
see https://git.interhacker.space/teamlaser/redilysis for more informations
|
||||
about the redilysis project
|
||||
|
||||
LICENCE : CC
|
||||
|
||||
by cocoa
|
||||
|
||||
|
||||
'''
|
||||
from __future__ import print_function
|
||||
import argparse
|
||||
import ast
|
||||
import os
|
||||
import math
|
||||
import random
|
||||
import redis
|
||||
import sys
|
||||
import time
|
||||
name = "generator::redilysis_lines"
|
||||
|
||||
def debug(*args, **kwargs):
|
||||
if( verbose == False ):
|
||||
return
|
||||
print(*args, file=sys.stderr, **kwargs)
|
||||
def msNow():
|
||||
return time.time()
|
||||
|
||||
CHAOS = 1
|
||||
REDIS_FREQ = 33
|
||||
|
||||
# General Args
|
||||
argsparser = argparse.ArgumentParser(description="Redilysis filter")
|
||||
argsparser.add_argument("-v","--verbose",action="store_true",help="Verbose")
|
||||
# Redis Args
|
||||
argsparser.add_argument("-i","--ip",help="IP address of the Redis server ",default="127.0.0.1",type=str)
|
||||
argsparser.add_argument("-p","--port",help="Port of the Redis server ",default="6379",type=str)
|
||||
argsparser.add_argument("-F","--redis-freq",help="Query Redis every x (in milliseconds). Default:{}".format(REDIS_FREQ),default=REDIS_FREQ,type=int)
|
||||
# General args
|
||||
argsparser.add_argument("-n","--nlines",help="number of lines on screen",default=60,type=int)
|
||||
argsparser.add_argument("-x","--centerX",help="geometrical center X position",default=400,type=int)
|
||||
argsparser.add_argument("-y","--centerY",help="geometrical center Y position",default=400,type=int)
|
||||
argsparser.add_argument("-W","--max-width",help="geometrical max width",default=800,type=int)
|
||||
argsparser.add_argument("-H","--max-height",help="geometrical max height",default=800,type=int)
|
||||
argsparser.add_argument("-f","--fps",help="Frame Per Second",default=30,type=int)
|
||||
|
||||
args = argsparser.parse_args()
|
||||
verbose = args.verbose
|
||||
ip = args.ip
|
||||
port = args.port
|
||||
fps = args.fps
|
||||
centerX = args.centerX
|
||||
centerY = args.centerY
|
||||
redisFreq = args.redis_freq / 1000
|
||||
maxWidth = args.max_width
|
||||
maxHeight = args.max_height
|
||||
nlines = args.nlines
|
||||
optimal_looptime = 1 / fps
|
||||
|
||||
redisKeys = ["spectrum_120","spectrum_10"]
|
||||
debug(name,"Redis Keys:{}".format(redisKeys))
|
||||
redisData = {}
|
||||
redisLastHit = msNow() - 99999
|
||||
r = redis.Redis(
|
||||
host=ip,
|
||||
port=port)
|
||||
|
||||
white = 16777215
|
||||
lineList = []
|
||||
|
||||
scroll_speed = int(maxHeight / nlines )
|
||||
line_length = int(maxWidth / 10)
|
||||
line_pattern = []
|
||||
|
||||
def rgb2int(rgb):
|
||||
#debug(name,"::rgb2int rbg:{}".format(rgb))
|
||||
return int('0x%02x%02x%02x' % tuple(rgb),0)
|
||||
|
||||
def spectrum_10( ):
|
||||
delList = []
|
||||
spectrum = ast.literal_eval(redisData["spectrum_10"])
|
||||
debug( name, "spectrum:{}".format(spectrum))
|
||||
# scroll lines
|
||||
for i,line in enumerate(lineList):
|
||||
skip_line = False
|
||||
new_y = int(line[0][1] + scroll_speed)
|
||||
if( new_y >= maxHeight ):
|
||||
debug(name,"{} > {}".format(new_y,maxHeight))
|
||||
debug(name,"delete:{}".format(i))
|
||||
delList.append(i)
|
||||
continue
|
||||
|
||||
for j,point in enumerate(line):
|
||||
line[j][1] = new_y
|
||||
lineList[i] = line
|
||||
|
||||
for i in delList:
|
||||
del lineList[i]
|
||||
|
||||
# new line
|
||||
currentLine = []
|
||||
for i in range(0,10):
|
||||
x = int(i * line_length)
|
||||
y = 0
|
||||
# get frequency level
|
||||
level = spectrum[i]
|
||||
# get color
|
||||
comp = int(255*level)
|
||||
color = rgb2int( (comp,comp,comp))
|
||||
# new point
|
||||
currentLine.append( [x,y,color] )
|
||||
|
||||
# add line to list
|
||||
lineList.append( currentLine)
|
||||
|
||||
|
||||
def refreshRedis():
|
||||
global redisLastHit
|
||||
global redisData
|
||||
# Skip if cache is sufficent
|
||||
diff = msNow() - redisLastHit
|
||||
if diff < redisFreq :
|
||||
#debug(name, "refreshRedis not updating redis, {} < {}".format(diff, redisFreq))
|
||||
pass
|
||||
else:
|
||||
#debug(name, "refreshRedis updating redis, {} > {}".format(diff, redisFreq))
|
||||
redisLastHit = msNow()
|
||||
for key in redisKeys:
|
||||
redisData[key] = r.get(key).decode('ascii')
|
||||
#debug(name,"refreshRedis key:{} value:{}".format(key,redisData[key]))
|
||||
# Only update the TTLs
|
||||
if 'bpm' in redisKeys:
|
||||
redisData['bpm_pttl'] = r.pttl('bpm')
|
||||
#debug(name,"refreshRedis key:bpm_ttl value:{}".format(redisData["bpm_pttl"]))
|
||||
#debug(name,"redisData:{}".format(redisData))
|
||||
return True
|
||||
|
||||
def linelistToPoints( lineList ):
|
||||
pl = []
|
||||
for i,line in enumerate(lineList):
|
||||
# add a blank point
|
||||
pl.append([ line[0][0], line[0][1], 0 ])
|
||||
# append all the points of the line
|
||||
pl += line
|
||||
#debug(name,"pl:{}".format(pl))
|
||||
debug(name,"pl length:{}".format(len(pl)))
|
||||
return pl
|
||||
|
||||
try:
|
||||
while True:
|
||||
refreshRedis()
|
||||
start = time.time()
|
||||
# Do the thing
|
||||
pointsList = spectrum_10()
|
||||
print( linelistToPoints(lineList), flush=True )
|
||||
looptime = time.time() - start
|
||||
# debug(name+" looptime:"+str(looptime))
|
||||
if( looptime < optimal_looptime ):
|
||||
time.sleep( optimal_looptime - looptime)
|
||||
# debug(name+" micro sleep:"+str( optimal_looptime - looptime))
|
||||
except EOFError:
|
||||
debug(name+" break")# no more information
|
||||
|
||||
288
clitools/generators/redilysis_particles.py
Executable file
288
clitools/generators/redilysis_particles.py
Executable file
|
|
@ -0,0 +1,288 @@
|
|||
#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# -*- mode: Python -*-
|
||||
|
||||
|
||||
'''
|
||||
|
||||
v0.1.0
|
||||
|
||||
|
||||
LICENCE : CC
|
||||
|
||||
by cocoa
|
||||
|
||||
'''
|
||||
from __future__ import print_function
|
||||
import math
|
||||
import random
|
||||
import sys
|
||||
import os
|
||||
import time
|
||||
import redis
|
||||
import ast
|
||||
import argparse
|
||||
|
||||
|
||||
MAX_PARTICLES = 50
|
||||
MAX_TIME = 500
|
||||
|
||||
argsparser = argparse.ArgumentParser(description="Dummy generator")
|
||||
argsparser.add_argument("-f","--fps",help="Frame Per Second",default=30,type=int)
|
||||
argsparser.add_argument("-v","--verbose",action="store_true",help="Verbose output")
|
||||
# Redis Args
|
||||
argsparser.add_argument("-i","--ip",help="IP address of the Redis server ",default="127.0.0.1",type=str)
|
||||
argsparser.add_argument("-p","--port",help="Port of the Redis server ",default="6379",type=str)
|
||||
#
|
||||
argsparser.add_argument("-M","--max-particles",help="Max Particles. Default:{}".format(MAX_PARTICLES),default=MAX_PARTICLES,type=int)
|
||||
argsparser.add_argument("-m","--max-time",help="Max Particles. Default:{}".format(MAX_TIME),default=MAX_TIME,type=int)
|
||||
|
||||
|
||||
args = argsparser.parse_args()
|
||||
verbose = args.verbose
|
||||
ip = args.ip
|
||||
port = args.port
|
||||
max_particles = args.max_particles
|
||||
max_time = args.max_time
|
||||
|
||||
def debug(*args, **kwargs):
|
||||
if( verbose == False ):
|
||||
return
|
||||
print(*args, file=sys.stderr, **kwargs)
|
||||
|
||||
|
||||
def rgb2int(rgb):
|
||||
#debug(name,"::rgb2int rbg:{}".format(rgb))
|
||||
return int('0x%02x%02x%02x' % tuple(rgb),0)
|
||||
|
||||
def spectrum_120( ):
|
||||
return ast.literal_eval(redisData["spectrum_10"])
|
||||
|
||||
|
||||
def rgb2int(rgb):
|
||||
#debug(name,"::rgb2int rbg:{}".format(rgb))
|
||||
return int('0x%02x%02x%02x' % tuple(rgb),0)
|
||||
|
||||
def msNow():
|
||||
return time.time()
|
||||
|
||||
def refreshRedis():
|
||||
global redisData
|
||||
for key in redisKeys:
|
||||
redisData[key] = ast.literal_eval(r.get(key).decode('ascii'))
|
||||
|
||||
name="generator::redilisys_particles"
|
||||
|
||||
class UnpreparedParticle(Exception):
|
||||
pass
|
||||
|
||||
class Particle(object):
|
||||
def __init__(self, x, y, m):
|
||||
self.x = x
|
||||
self.y = y
|
||||
self.m = m
|
||||
self.dx = 0
|
||||
self.dy = 0
|
||||
self.connectedTo = []
|
||||
|
||||
self.decay = random.randint(10,max_time)
|
||||
self.color = (random.randint(128,256) - int(12.8 * self.m),
|
||||
random.randint(128,256) - int(12.8 * self.m),
|
||||
random.randint(128,256) - int(12.8 * self.m))
|
||||
self.color = (255,255,255)
|
||||
#debug( self.color )
|
||||
|
||||
def interact(self, bodies):
|
||||
self.connectedTo = []
|
||||
spec = redisData["spectrum_10"]
|
||||
power = int(sum(spec[4:6]))
|
||||
for other in bodies:
|
||||
if other is self:
|
||||
continue
|
||||
dx = other.x - self.x
|
||||
dy = other.y - self.y
|
||||
dist = math.sqrt(dx*dx + dy*dy)
|
||||
if dist == 0:
|
||||
dist = 1
|
||||
if dist < 100 and random.randint(0,power) > 0.5 :
|
||||
self.connectedTo.append(other)
|
||||
self.decay += 2
|
||||
factor = other.m / dist**2
|
||||
high_power = sum(spec[8:9]) if sum(spec[8:9]) != 0 else 0.01
|
||||
self.dx += (dx * factor * self.m)
|
||||
self.dy += (dy * factor * self.m)
|
||||
#print "factor %f" % (factor,)
|
||||
|
||||
def move(self):
|
||||
spec = redisData["spectrum_10"]
|
||||
x_friction = (2.2-(1+spec[7]/2))
|
||||
y_friction = (2.2-(1+spec[7]/2))
|
||||
#x_friction = 1.02
|
||||
#y_friction = 1.04
|
||||
self.dx /= x_friction if x_friction != 0 else 0.01
|
||||
self.dy /= y_friction if y_friction != 0 else 0.01
|
||||
self.x += self.dx
|
||||
self.y += self.dy
|
||||
if self.x > max_width:
|
||||
self.dx = - self.dx /8
|
||||
self.x = max_width
|
||||
if self.x < 1:
|
||||
self.dx = - self.dx /8
|
||||
self.x = 1
|
||||
if self.y > max_height:
|
||||
self.dy = - self.dy /4
|
||||
self.y = max_height
|
||||
if self.y < 1:
|
||||
self.dy = - self.dy /4
|
||||
self.y = 1
|
||||
#print "(%.2f,%.2f) -> (%.2f,%.2f)" % (ox, oy, self.x, self.y)
|
||||
|
||||
def attractor(self,attractor):
|
||||
spec = redisData["spectrum_10"]
|
||||
power = sum(spec[0:4])/3
|
||||
# If we're going in the direction of center, reverse
|
||||
next_x = self.x + self.dx
|
||||
next_y = self.y + self.dy
|
||||
next_dx = attractor["x"] - self.x
|
||||
next_dy = attractor["y"] - self.y
|
||||
next_dist = math.sqrt(next_dx*next_dx + next_dy*next_dy)
|
||||
|
||||
dx = attractor["x"] - self.x
|
||||
dy = attractor["y"] - self.y
|
||||
dist = math.sqrt(dx*dx + dy*dy)
|
||||
if dist == 0:
|
||||
dist = 1
|
||||
factor = power/ dist**2
|
||||
x_acceleration = (dx * factor * power * power)
|
||||
y_acceleration = (dx * factor * power * power)
|
||||
|
||||
|
||||
if next_dist > dist:
|
||||
self.dx -= x_acceleration * power
|
||||
self.dy -= y_acceleration * power
|
||||
else:
|
||||
self.dx += x_acceleration
|
||||
self.dy += y_acceleration
|
||||
|
||||
|
||||
class Attractor(Particle):
|
||||
def move(self):
|
||||
pass
|
||||
|
||||
|
||||
class ParticleViewer(object):
|
||||
def __init__(self, particles, size=(800,800)):
|
||||
(self.width, self.height) = size
|
||||
self.size = size
|
||||
self.particles = particles
|
||||
self.xoff = 0
|
||||
self.yoff = 0
|
||||
self.scalefactor = 1
|
||||
|
||||
def redraw(self):
|
||||
|
||||
pl = []
|
||||
drawnVectors = []
|
||||
for p in self.particles:
|
||||
x = int(self.scalefactor * p.x) - self.xoff
|
||||
y = int(self.scalefactor * p.y) - self.yoff
|
||||
if x > max_width:
|
||||
x = max_width
|
||||
if x < 1:
|
||||
x = 1
|
||||
if y > max_height:
|
||||
y = max_height
|
||||
if y < 1:
|
||||
y = 1
|
||||
|
||||
color = rgb2int(p.color)
|
||||
pl.append([x+1,y+1,0])
|
||||
pl.append([x+1,y+1,color])
|
||||
pl.append([x,y,color])
|
||||
|
||||
for other in p.connectedTo:
|
||||
|
||||
if [other,self] in drawnVectors:
|
||||
continue
|
||||
drawnVectors.append([other,self])
|
||||
pl.append([x,y,0])
|
||||
pl.append([x,y,color])
|
||||
pl.append([other.x,other.y,color])
|
||||
|
||||
print(pl,flush = True)
|
||||
|
||||
def decayParticles(self):
|
||||
for i,p in enumerate(self.particles):
|
||||
# Handle positional decay
|
||||
if p.decay == 0:
|
||||
del self.particles[i]
|
||||
continue
|
||||
p.decay = p.decay - 1
|
||||
# Handle color decay
|
||||
n = int(255 * (p.decay / max_time ))
|
||||
p.color = (n,n,n)
|
||||
|
||||
|
||||
def emitParticles(self):
|
||||
spec = redisData["spectrum_10"]
|
||||
power = sum(spec[6:])
|
||||
if len(self.particles ) > math.sqrt(max_particles):
|
||||
if len(self.particles) > max_particles:
|
||||
return
|
||||
if random.random() > power:
|
||||
return
|
||||
# x is either left or right
|
||||
d = 600
|
||||
rx = 100 if random.randint(0,1) else 700
|
||||
#rx = random.randint(1,max_width)
|
||||
ry = random.randint(1,max_height)
|
||||
spec = redisData["spectrum_10"]
|
||||
m = random.randint(1,1+int(10*spec[7]))
|
||||
particles.append(Particle(rx, ry, m))
|
||||
|
||||
|
||||
def tick(self):
|
||||
self.decayParticles()
|
||||
self.emitParticles()
|
||||
for p in self.particles:
|
||||
p.interact(self.particles)
|
||||
p.attractor({
|
||||
"x":max_width/2,
|
||||
"y":max_height/2
|
||||
})
|
||||
for p in particles:
|
||||
p.move()
|
||||
self.redraw()
|
||||
|
||||
def scale(self, factor):
|
||||
self.scalefactor += factor
|
||||
|
||||
|
||||
|
||||
|
||||
max_width = 800
|
||||
max_height = 800
|
||||
redisKeys = ["spectrum_120","spectrum_10"]
|
||||
redisData = {}
|
||||
redisLastHit = msNow() - 99999
|
||||
r = redis.Redis(
|
||||
host=ip,
|
||||
port=port)
|
||||
|
||||
white = 16777215
|
||||
|
||||
refreshRedis()
|
||||
if __name__ == "__main__":
|
||||
particles = []
|
||||
# particles.append(Attractor(320, 200, 10))
|
||||
# particles.append(Attractor(100, 100, 10))
|
||||
|
||||
win = ParticleViewer(particles)
|
||||
try:
|
||||
while True:
|
||||
win.tick()
|
||||
refreshRedis()
|
||||
time.sleep(.03)
|
||||
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
93
clitools/generators/text.py
Normal file
93
clitools/generators/text.py
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# -*- mode: Python -*-
|
||||
|
||||
'''
|
||||
|
||||
A text generators using Hershey fonts
|
||||
https://pypi.org/project/Hershey-Fonts/
|
||||
|
||||
pip3 install Hershey-Fonts
|
||||
|
||||
v0.1.0
|
||||
|
||||
Font list :
|
||||
'futural', 'astrology', 'cursive', 'cyrilc_1', 'cyrillic', 'futuram', 'gothgbt', 'gothgrt',
|
||||
'gothiceng', 'gothicger', 'gothicita', 'gothitt', 'greek', 'greekc', 'greeks', 'japanese',
|
||||
'markers', 'mathlow', 'mathupp', 'meteorology', 'music', 'rowmand', 'rowmans', 'rowmant',
|
||||
'scriptc', 'scripts', 'symbolic', 'timesg', 'timesi', 'timesib', 'timesr', 'timesrb'
|
||||
|
||||
LICENCE : CC
|
||||
|
||||
by cocoa and Sam Neurohack
|
||||
|
||||
'''
|
||||
|
||||
from __future__ import print_function
|
||||
import time
|
||||
import argparse
|
||||
import sys
|
||||
from HersheyFonts import HersheyFonts
|
||||
|
||||
name="generator::text"
|
||||
|
||||
|
||||
def debug(*args, **kwargs):
|
||||
if( verbose == False ):
|
||||
return
|
||||
print(*args, file=sys.stderr, **kwargs)
|
||||
|
||||
|
||||
argsparser = argparse.ArgumentParser(description="Text generator")
|
||||
argsparser.add_argument("-f","--fps",help="Frame Per Second",default=30,type=int)
|
||||
argsparser.add_argument("-v","--verbose",action="store_true",help="Verbose output")
|
||||
argsparser.add_argument("-t","--text",help="Text to display",default="hello",type=str)
|
||||
argsparser.add_argument("-p","--police",help="Herschey font to use",default="futural",type=str)
|
||||
args = argsparser.parse_args()
|
||||
|
||||
fps=args.fps
|
||||
verbose=args.verbose
|
||||
|
||||
text = args.text
|
||||
fontname = args.police
|
||||
|
||||
optimal_looptime = 1 / fps
|
||||
debug(name+" optimal looptime "+str(optimal_looptime))
|
||||
|
||||
def rgb2int(rgb):
|
||||
return int('0x%02x%02x%02x' % tuple(rgb),0)
|
||||
|
||||
# Useful variables init.
|
||||
white = rgb2int((255,255,255))
|
||||
red = rgb2int((255,0,0))
|
||||
blue = rgb2int((0,0,255))
|
||||
green = rgb2int((0,255,0))
|
||||
|
||||
color = 65280
|
||||
|
||||
shape =[]
|
||||
|
||||
Allfonts = ['futural', 'astrology', 'cursive', 'cyrilc_1', 'cyrillic', 'futuram', 'gothgbt', 'gothgrt', 'gothiceng', 'gothicger', 'gothicita', 'gothitt', 'greek', 'greekc', 'greeks', 'japanese', 'markers', 'mathlow', 'mathupp', 'meteorology', 'music', 'rowmand', 'rowmans', 'rowmant', 'scriptc', 'scripts', 'symbolic', 'timesg', 'timesi', 'timesib', 'timesr', 'timesrb']
|
||||
|
||||
thefont = HersheyFonts()
|
||||
#thefont.load_default_font()
|
||||
thefont.load_default_font(fontname)
|
||||
thefont.normalize_rendering(120)
|
||||
|
||||
for (x1, y1), (x2, y2) in thefont.lines_for_text(text):
|
||||
shape.append([x1, -y1+400, color])
|
||||
shape.append([x2 ,-y2+400, color])
|
||||
|
||||
while True:
|
||||
|
||||
start = time.time()
|
||||
print(shape, flush=True);
|
||||
|
||||
looptime = time.time() - start
|
||||
if( looptime < optimal_looptime ):
|
||||
time.sleep( optimal_looptime - looptime)
|
||||
debug(name+" micro sleep:"+str( optimal_looptime - looptime))
|
||||
|
||||
|
||||
#[[14.285714285714286, 100.0, 14.285714285714286, 25.0, 65280], [64.28571428571429, 100.0, 64.28571428571429, 25.0, 65280], [14.285714285714286, 64.28571428571429, 64.28571428571429, 64.28571428571429, 65280], [89.28571428571428, 53.57142857142858, 132.14285714285714, 53.57142857142858, 65280], [132.14285714285714, 53.57142857142858, 132.14285714285714, 60.714285714285715, 65280], [132.14285714285714, 60.714285714285715, 128.57142857142856, 67.85714285714286, 65280], [128.57142857142856, 67.85714285714286, 125.0, 71.42857142857143, 65280], [125.0, 71.42857142857143, 117.85714285714286, 75.0, 65280], [117.85714285714286, 75.0, 107.14285714285714, 75.0, 65280], [107.14285714285714, 75.0, 100.0, 71.42857142857143, 65280], [100.0, 71.42857142857143, 92.85714285714286, 64.28571428571429, 65280], [92.85714285714286, 64.28571428571429, 89.28571428571428, 53.57142857142858, 65280], [89.28571428571428, 53.57142857142858, 89.28571428571428, 46.42857142857143, 65280], [89.28571428571428, 46.42857142857143, 92.85714285714286, 35.714285714285715, 65280], [92.85714285714286, 35.714285714285715, 100.0, 28.571428571428573, 65280], [100.0, 28.571428571428573, 107.14285714285714, 25.0, 65280], [107.14285714285714, 25.0, 117.85714285714286, 25.0, 65280], [117.85714285714286, 25.0, 125.0, 28.571428571428573, 65280], [125.0, 28.571428571428573, 132.14285714285714, 35.714285714285715, 65280]]
|
||||
|
||||
175
clitools/generators/trckr.py
Normal file
175
clitools/generators/trckr.py
Normal file
|
|
@ -0,0 +1,175 @@
|
|||
#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# -*- mode: Python -*-
|
||||
|
||||
'''
|
||||
|
||||
A Face tracker
|
||||
v0.1.0
|
||||
|
||||
Get all points fom redis /trckr/frame/WSclientID points
|
||||
|
||||
LICENCE : CC
|
||||
|
||||
by cocoa and Sam Neurohack
|
||||
|
||||
'''
|
||||
|
||||
from __future__ import print_function
|
||||
import time
|
||||
import argparse
|
||||
import sys
|
||||
import redis
|
||||
import ast
|
||||
|
||||
name="generator::trckr"
|
||||
|
||||
|
||||
def debug(*args, **kwargs):
|
||||
if( verbose == False ):
|
||||
return
|
||||
print(*args, file=sys.stderr, **kwargs)
|
||||
|
||||
|
||||
argsparser = argparse.ArgumentParser(description="Face tracking generator")
|
||||
argsparser.add_argument("-f","--fps",help="Frame Per Second",default=30,type=int)
|
||||
argsparser.add_argument("-v","--verbose",action="store_true",help="Verbose output")
|
||||
argsparser.add_argument("-i","--id",help="Trckr client ID",default="0",type=str)
|
||||
argsparser.add_argument("-s","--server",help="redis server IP (127.0.0.1 by default)", type=str)
|
||||
args = argsparser.parse_args()
|
||||
|
||||
fps=args.fps
|
||||
verbose=args.verbose
|
||||
idclient = args.id
|
||||
|
||||
if args.server:
|
||||
redisIP = args.server
|
||||
else:
|
||||
redisIP = "127.0.0.1"
|
||||
|
||||
|
||||
|
||||
optimal_looptime = 1 / fps
|
||||
debug(name+" optimal looptime "+str(optimal_looptime))
|
||||
|
||||
color = 65280
|
||||
|
||||
|
||||
def rgb2int(rgb):
|
||||
return int('0x%02x%02x%02x' % tuple(rgb),0)
|
||||
|
||||
# Useful variables init.
|
||||
white = rgb2int((255,255,255))
|
||||
red = rgb2int((255,0,0))
|
||||
blue = rgb2int((0,0,255))
|
||||
green = rgb2int((0,255,0))
|
||||
|
||||
#
|
||||
# Redis functions
|
||||
#
|
||||
|
||||
r = redis.StrictRedis(host=redisIP , port=6379, db=0)
|
||||
|
||||
# read from redis key
|
||||
def fromKey(keyname):
|
||||
|
||||
return r.get(keyname)
|
||||
|
||||
# Write to redis key
|
||||
def toKey(keyname,keyvalue):
|
||||
return r.set(keyname,keyvalue)
|
||||
|
||||
#
|
||||
# Trckr faces
|
||||
#
|
||||
|
||||
TrckrPts = [[159.39, 137.68], [155.12, 159.31], [155.56, 180.13], [159.81, 201.6], [170.48, 220.51], [187.46, 234.81], [208.4, 244.68], [229.46, 248.21], [246.44, 244.91], [259.69, 234.83], [270.95, 221.51], [278.54, 204.66], [283.53, 185.63], [286.27, 165.79], [284.72, 144.84], [280.06, 125.01], [274.35, 118.7], [260.71, 117.23], [249.52, 118.86], [182.04, 121.5], [193.63, 114.79], [210.24, 114.77], [222.35, 117.57], [190.6, 137.49], [203.59, 132.42], [214.75, 137.58], [203.04, 140.46], [203.32, 136.53], [272.45, 141.57], [263.33, 135.42], [250.31, 138.89], [262.15, 143.27], [261.99, 139.37], [235.82, 131.74], [221.87, 156.09], [213.66, 165.88], [219.28, 173.53], [236.3, 175.25], [249.02, 174.4], [254.22, 167.81], [248.83, 157.39], [237.94, 147.51], [227.01, 168.39], [245.68, 170.02], [204.94, 197.32], [217.56, 192.77], [228.27, 190.55], [234.66, 192.19], [240.47, 191.09], [247.96, 193.87], [254.52, 199.19], [249.35, 204.25], [242.74, 207.16], [233.2, 207.87], [222.13, 206.52], [212.44, 203.09], [220.34, 198.74], [233.31, 200.04], [244.0, 199.6], [244.27, 197.8], [233.81, 197.44], [220.88, 196.99], [239.57, 162.69], [196.52, 133.86], [210.2, 133.98], [209.43, 139.41], [196.59, 139.47], [268.99, 137.59], [256.36, 136.02], [255.95, 141.5], [267.9, 142.85]]
|
||||
toKey('/trckr/frame/0',str(TrckrPts))
|
||||
|
||||
# get absolute face position points
|
||||
def getPART(TrckrPts, pose_points):
|
||||
|
||||
dots = []
|
||||
#debug(pose_points)
|
||||
#debug(TrckrPts)
|
||||
for dot in pose_points:
|
||||
dots.append((TrckrPts[dot][0], TrckrPts[dot][1],0))
|
||||
#debug(dots)
|
||||
return dots
|
||||
|
||||
|
||||
# Face keypoints
|
||||
def face(TrckrPts):
|
||||
pose_points = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14]
|
||||
return getPART(TrckrPts, pose_points)
|
||||
|
||||
def browL(TrckrPts):
|
||||
pose_points = [15,16,17,18]
|
||||
return getPART(TrckrPts, pose_points)
|
||||
|
||||
def browR(TrckrPts):
|
||||
pose_points = [22,21,20,19]
|
||||
return getPART(TrckrPts, pose_points)
|
||||
|
||||
def eyeR(TrckrPts):
|
||||
pose_points = [25,64,24,63,23,66,26,65,25]
|
||||
return getPART(TrckrPts, pose_points)
|
||||
|
||||
def eyeL(TrckrPts):
|
||||
pose_points = [28,67,29,68,30,69,31,28]
|
||||
return getPART(TrckrPts, pose_points)
|
||||
|
||||
def pupR(TrckrPts):
|
||||
pose_points = [27]
|
||||
return getPART(TrckrPts, pose_points)
|
||||
|
||||
def pupL(TrckrPts):
|
||||
pose_points = [32]
|
||||
return getPART(TrckrPts, pose_points)
|
||||
|
||||
|
||||
def nose1(TrckrPts):
|
||||
pose_points = [62,41,33]
|
||||
return getPART(TrckrPts, pose_points)
|
||||
|
||||
def nose2(TrckrPts):
|
||||
pose_points = [40,39,38,43,37,42,36,35,34]
|
||||
return getPART(TrckrPts, pose_points)
|
||||
|
||||
def mouth(TrckrPts):
|
||||
pose_points = [50,49,48,47,46,45,44,55,54,53,52,51,50]
|
||||
return getPART(TrckrPts, pose_points)
|
||||
|
||||
def mouthfull(TrckrPts):
|
||||
pose_points = [50,49,48,47,46,45,44,55,54,53,52,51,50,59,60,61,44,56,57,58,50]
|
||||
return getPART(TrckrPts, pose_points)
|
||||
|
||||
|
||||
while True:
|
||||
|
||||
start = time.time()
|
||||
shape =[]
|
||||
points = ast.literal_eval(fromKey('/trckr/frame/'+idclient).decode('ascii'))
|
||||
shape.append(browL(points))
|
||||
shape.append(eyeL(points))
|
||||
shape.append(browR(points))
|
||||
shape.append(eyeR(points))
|
||||
shape.append(pupL(points))
|
||||
shape.append(pupR(points))
|
||||
shape.append(nose1(points))
|
||||
shape.append(nose2(points))
|
||||
shape.append(mouthfull(points))
|
||||
line = str(shape)
|
||||
line = line.replace("(",'[')
|
||||
line = line.replace(")",']')
|
||||
line = "[{}]".format(line)
|
||||
print(line, flush=True);
|
||||
#debug(shape)
|
||||
#print(shape, flush=True);
|
||||
|
||||
looptime = time.time() - start
|
||||
if( looptime < optimal_looptime ):
|
||||
time.sleep( optimal_looptime - looptime)
|
||||
debug(name+" micro sleep:"+str( optimal_looptime - looptime))
|
||||
|
||||
|
||||
194
clitools/generators/tunnel.py
Executable file
194
clitools/generators/tunnel.py
Executable file
|
|
@ -0,0 +1,194 @@
|
|||
#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# -*- mode: Python -*-
|
||||
|
||||
|
||||
'''
|
||||
|
||||
Woooh! I'm progressing in a tunnel !
|
||||
v0.1.0
|
||||
|
||||
Use it to test your filters and outputs
|
||||
|
||||
LICENCE : CC
|
||||
|
||||
by cocoa
|
||||
|
||||
'''
|
||||
|
||||
from __future__ import print_function
|
||||
import argparse
|
||||
import math
|
||||
import random
|
||||
import sys
|
||||
import time
|
||||
name="generator::tunnel"
|
||||
|
||||
def debug(*args, **kwargs):
|
||||
if( verbose == False ):
|
||||
return
|
||||
print(*args, file=sys.stderr, **kwargs)
|
||||
|
||||
|
||||
argsparser = argparse.ArgumentParser(description="tunnel generator")
|
||||
argsparser.add_argument("-c","--color",help="Color",default=65280,type=int)
|
||||
argsparser.add_argument("-f","--fps",help="Frame Per Second",default=30,type=int)
|
||||
argsparser.add_argument("-i","--interval",help="point per shape interval",default=30,type=int)
|
||||
argsparser.add_argument("-m","--max-size",help="maximum size for objects",default=400,type=int)
|
||||
argsparser.add_argument("-r","--randomize",help="center randomization",default=5,type=int)
|
||||
argsparser.add_argument("-s","--speed",help="point per frame progress",default=3,type=int)
|
||||
argsparser.add_argument("-v","--verbose",action="store_true",help="Verbose output")
|
||||
argsparser.add_argument("-x","--centerX",help="geometrical center X position",default=400,type=int)
|
||||
argsparser.add_argument("-y","--centerY",help="geometrical center Y position",default=400,type=int)
|
||||
|
||||
args = argsparser.parse_args()
|
||||
centerX = args.centerX
|
||||
centerY = args.centerY
|
||||
color = args.color
|
||||
fps = args.fps
|
||||
interval = args.interval
|
||||
max_size = args.max_size
|
||||
randomize = args.randomize
|
||||
speed = args.speed
|
||||
verbose = args.verbose
|
||||
|
||||
origSpeed = speed
|
||||
optimal_looptime = 1 / fps
|
||||
square = [
|
||||
[-1,1],
|
||||
[1,1],
|
||||
[1,-1],
|
||||
[-1,-1],
|
||||
[-1,1]
|
||||
]
|
||||
|
||||
circle = [[1,0],
|
||||
[0.9238795325112867,0.3826834323650898],
|
||||
[0.7071067811865476,0.7071067811865475],
|
||||
[0.38268343236508984,0.9238795325112867],
|
||||
[0,1.0],
|
||||
[-0.3826834323650897,0.9238795325112867],
|
||||
[-0.7071067811865475,0.7071067811865476],
|
||||
[-0.9238795325112867,0.3826834323650899],
|
||||
[-1.0,0],
|
||||
[-0.9238795325112868,-0.38268343236508967],
|
||||
[-0.7071067811865477,-0.7071067811865475],
|
||||
[-0.38268343236509034,-0.9238795325112865],
|
||||
[0,-1.0],
|
||||
[0.38268343236509,-0.9238795325112866],
|
||||
[0.707106781186548,-0.707106781186547],
|
||||
[0.9238795325112872,-0.3826834323650887],
|
||||
[1,0]]
|
||||
|
||||
shape = circle
|
||||
currentCenter = [centerX, centerY]
|
||||
centerVector= [0,0]
|
||||
# tweak random basis
|
||||
if randomize % 2 == 1:
|
||||
randomize += 1
|
||||
debug(name,"randomize:{}".format(randomize))
|
||||
centerRand = int(math.sqrt(randomize) / 4 ) + 1
|
||||
debug( name, "centerRand:{}".format(centerRand ) )
|
||||
class polylineGenerator( object ):
|
||||
|
||||
def __init__( self ):
|
||||
self.polylineList = [[0,[currentCenter[0],currentCenter[1]]]]
|
||||
self.buf = []
|
||||
|
||||
def init(self):
|
||||
finished = False
|
||||
while not finished:
|
||||
finished = self.increment()
|
||||
debug(name,"init done:{}".format(self.polylineList))
|
||||
def draw( self ):
|
||||
self.buf = []
|
||||
for it_pl, infoList in enumerate(self.polylineList):
|
||||
size = infoList[0]
|
||||
center = infoList[1]
|
||||
for it_sqr, point in enumerate(shape):
|
||||
x = int( center[0] + point[0]*size )
|
||||
y = int( center[1] + point[1]*size )
|
||||
# Add an invisible point in first location
|
||||
if 0 == it_sqr:
|
||||
self.buf.append([x,y,0])
|
||||
self.buf.append([x,y,color])
|
||||
#debug( name, "buf size:", str(len(self.buf)) )
|
||||
return self.buf
|
||||
|
||||
def increment(self):
|
||||
global speed
|
||||
self.buffer = []
|
||||
min_size = 9999
|
||||
delList = []
|
||||
if randomize :
|
||||
# Change the vector
|
||||
centerVector[0] += random.randrange( -centerRand,centerRand )
|
||||
centerVector[1] += random.randrange( -centerRand,centerRand )
|
||||
# Modify the vector if it is over the limit
|
||||
if currentCenter[0] + centerVector[0] >= centerX + randomize or currentCenter[0] + centerVector[0] <= centerX - randomize:
|
||||
centerVector[0] = 0
|
||||
if currentCenter[1] + centerVector[1] >= centerY + randomize or currentCenter[1] +centerVector[1] <= centerY - randomize:
|
||||
centerVector[1] = 0
|
||||
currentCenter[0] += centerVector[0]
|
||||
currentCenter[1] += centerVector[1]
|
||||
# Change speed
|
||||
speed += int( random.randrange( int(-origSpeed),origSpeed ) )
|
||||
if speed < origSpeed :
|
||||
speed = origSpeed
|
||||
elif speed > (origSpeed + randomize / 2) :
|
||||
speed = origSpeed + randomize / 2
|
||||
#debug(name, "currentCenter:{} speed:{}".format(currentCenter,speed))
|
||||
|
||||
for i, shapeInfo in enumerate(self.polylineList):
|
||||
size = shapeInfo[0]
|
||||
# Augment speed with size
|
||||
"""
|
||||
size = 0 : += sqrt(speed)
|
||||
size = half max size : +=speed
|
||||
|
||||
"""
|
||||
if size < max_size / 4:
|
||||
size += math.pow(speed, 0.1)
|
||||
elif size < max_size / 3:
|
||||
size += math.pow(speed, 0.25)
|
||||
elif size < max_size / 2:
|
||||
size += math.pow(speed, 0.5)
|
||||
else:
|
||||
size += math.pow(speed, 1.25)
|
||||
if size < min_size : min_size = size
|
||||
if size > max_size : delList.append(i)
|
||||
self.polylineList[i][0] = size
|
||||
for i in delList:
|
||||
del self.polylineList[i]
|
||||
#debug(name, "polyline:",self.polylineList)
|
||||
if min_size >= interval:
|
||||
debug(name, "new shape")
|
||||
self.polylineList.append([0,[currentCenter[0],currentCenter[1]]])
|
||||
|
||||
# Return True if we delete a shape
|
||||
|
||||
if len(delList):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
pgen = polylineGenerator()
|
||||
pgen.init()
|
||||
|
||||
while True:
|
||||
start = time.time()
|
||||
|
||||
# Generate
|
||||
pgen.increment()
|
||||
|
||||
# send
|
||||
pl = pgen.draw()
|
||||
print(pl, flush=True)
|
||||
#debug(name,"output:{}".format(pl))
|
||||
|
||||
looptime = time.time() - start
|
||||
if( looptime < optimal_looptime ):
|
||||
time.sleep( optimal_looptime - looptime)
|
||||
#debug(name+" micro sleep:"+str( optimal_looptime - looptime))
|
||||
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue