diff --git a/clitools/exports/toRedis.py b/clitools/exports/toRedis.py index 626991a..36381b8 100644 --- a/clitools/exports/toRedis.py +++ b/clitools/exports/toRedis.py @@ -8,11 +8,11 @@ redis exporter v0.1.0 -A basic exporter +A basic exporter LICENCE : CC -by cocoa +by cocoa ''' @@ -21,7 +21,7 @@ import sys import os import argparse import redis -import time +import time argsparser = argparse.ArgumentParser(description="Redis exporter LJ") argsparser.add_argument("-i","--ip",help="IP address of the Redis server ",default="127.0.0.1",type=str) @@ -47,6 +47,7 @@ try: line = sys.stdin.readline() if line == "": time.sleep(0.01) + continue line = line.rstrip('\n') line=line[1:-1] line = line.replace("[",'(') diff --git a/clitools/filters/kaleidoscope.py b/clitools/filters/kaleidoscope.py index 5ca4396..8f874b3 100755 --- a/clitools/filters/kaleidoscope.py +++ b/clitools/filters/kaleidoscope.py @@ -162,8 +162,7 @@ try: pointsList = ast.literal_eval(line) # Do the filter result = kaleidoscope( pointsList ) - print( result, flush=True ) - + if len(result) : print( result, flush=True ) looptime = time.time() - start # debug(name+" looptime:"+str(looptime)) if( looptime < optimal_looptime ): diff --git a/clitools/filters/redilysis_colors.py b/clitools/filters/redilysis_colors.py old mode 100644 new mode 100755 index 230fa08..2b4abc1 --- a/clitools/filters/redilysis_colors.py +++ b/clitools/filters/redilysis_colors.py @@ -1,4 +1,3 @@ - #!/usr/bin/python3 # -*- coding: utf-8 -*- # -*- mode: Python -*- @@ -145,8 +144,11 @@ def default( pl ): colorTuple = int2rgb(ocolor) x = point[0] dist = abs(x - max_width/2) - key = int(2* dist / max_width * 8) - power = spect[key] / spect10Correct[key] * chaos + key = int(2* dist / max_width * 7) + try: + power = spect[key] / spect10Correct[key] * chaos + except: + pass color = [] for i in colorTuple: new_color = int(i * power) diff --git a/clitools/generators/blank.py b/clitools/generators/blank.py new file mode 100755 index 0000000..657bc5a --- /dev/null +++ b/clitools/generators/blank.py @@ -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)) + + diff --git a/clitools/generators/dummy.py b/clitools/generators/dummy.py index 6a94eb0..8f7eb2c 100755 --- a/clitools/generators/dummy.py +++ b/clitools/generators/dummy.py @@ -12,7 +12,7 @@ Use it to test your filters and outputs LICENCE : CC -by cocoa +by cocoa ''' @@ -28,17 +28,17 @@ def debug(*args, **kwargs): return print(*args, file=sys.stderr, **kwargs) - -argsparser = argparse.ArgumentParser(description="Dummy generator") +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() +args = argsparser.parse_args() fps=args.fps verbose=args.verbose optimal_looptime = 1 / fps debug(name+" optimal looptime "+str(optimal_looptime)) -color = 65280 +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)): @@ -71,7 +71,7 @@ mire = [ [400,450,color], ] -shape = mire +shape = mire while True: @@ -81,5 +81,5 @@ while True: if( looptime < optimal_looptime ): time.sleep( optimal_looptime - looptime) debug(name+" micro sleep:"+str( optimal_looptime - looptime)) - + diff --git a/clitools/generators/fromRedis.py b/clitools/generators/fromRedis.py new file mode 100755 index 0000000..8c65951 --- /dev/null +++ b/clitools/generators/fromRedis.py @@ -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)) + diff --git a/clitools/generators/tunnel.py b/clitools/generators/tunnel.py index f324475..437cb12 100755 --- a/clitools/generators/tunnel.py +++ b/clitools/generators/tunnel.py @@ -12,7 +12,7 @@ Use it to test your filters and outputs LICENCE : CC -by cocoa +by cocoa ''' @@ -52,7 +52,7 @@ randomize = args.randomize speed = args.speed verbose = args.verbose -origSpeed = speed +origSpeed = speed optimal_looptime = 1 / fps square = [ [-1,1], @@ -62,14 +62,32 @@ square = [ [-1,1] ] -shape = square +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 +centerRand = int(math.sqrt(randomize) / 4 ) + 1 debug( name, "centerRand:{}".format(centerRand ) ) class polylineGenerator( object ): @@ -103,10 +121,10 @@ class polylineGenerator( object ): min_size = 9999 delList = [] if randomize : - # Change the vector + # Change the vector centerVector[0] += random.randrange( -centerRand,centerRand ) centerVector[1] += random.randrange( -centerRand,centerRand ) - # Modify the vector if it is over the limit + # 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: @@ -115,19 +133,19 @@ class polylineGenerator( object ): currentCenter[1] += centerVector[1] # Change speed speed += int( random.randrange( int(-origSpeed),origSpeed ) ) - if speed < origSpeed : + if speed < origSpeed : speed = origSpeed elif speed > (origSpeed + randomize / 2) : - 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 + # Augment speed with size """ size = 0 : += sqrt(speed) size = half max size : +=speed - + """ if size < max_size / 4: size += math.pow(speed, 0.1) @@ -143,7 +161,7 @@ class polylineGenerator( object ): for i in delList: del self.polylineList[i] #debug(name, "polyline:",self.polylineList) - if min_size >= interval: + if min_size >= interval: debug(name, "new shape") self.polylineList.append([0,[currentCenter[0],currentCenter[1]]]) @@ -172,5 +190,5 @@ while True: if( looptime < optimal_looptime ): time.sleep( optimal_looptime - looptime) #debug(name+" micro sleep:"+str( optimal_looptime - looptime)) - + diff --git a/clitools/runner_lib.py b/clitools/runner_lib.py index 4cd5615..85ddbe3 100644 --- a/clitools/runner_lib.py +++ b/clitools/runner_lib.py @@ -10,6 +10,16 @@ import json from pathlib import Path import redis + +environ = { +# "REDIS_IP" : "127.0.0.1", + "REDIS_IP" : "192.168.2.44", + "REDIS_PORT" : "6379", + "REDIS_KEY" : "/pl/0/0", + "REDIS_SCENE" : "0", + "REDIS_LASER" : "0" +} + class bcolors: HL = '\033[31m' OKBLUE = '\033[94m' @@ -37,12 +47,12 @@ def intkey(): except ValueError: print("Error.") -current_id=0 -current_cmd="" -process = None -current_filename = "" -currentPlayList = [] -playlistsDir = Path("./playlists") +current_id = 0 +current_cmd = "" +process = None +current_filename = "" +currentPlayList = [] +playlistsDir = Path("./playlists") if not playlistsDir.is_dir() : playlistsDir.mkdir() def ask(q): @@ -105,10 +115,12 @@ def action_changeCommand( inc ): return True def action_match( k ): + global current_id, currentPlayList if int(k) > (len(currentPlayList) - 1): print( bcolors.HL + "This key does not exist" + bcolors.ENDC ) return False else : + _ok("Changed action id to {}.".format(k)) current_id = int(k) def action_runCommand(): @@ -155,7 +167,7 @@ def action_deleteCommand(): action_listAll() key = int(input()) # Exit early - if "x" == k: + if "x" == key: return(False) del currentPlayList[key] return True @@ -163,7 +175,7 @@ def action_deleteCommand(): def action_listAll(): - global currentPlayList, current_cmd + global currentPlayList, current_cmd, current_id print("\n--------------------------------------") for i,seq in enumerate(currentPlayList): pre="" @@ -232,7 +244,7 @@ def action_loadPlaylist(): print( bcolors.HL + "This key '{}' is not valid".format(k) + bcolors.ENDC ) return False - # Load file + # @todo replace with _loadPlaylist playlistFile = Path("./playlists/"+file_list[k].name) currentPlayList = json.loads(playlistFile.read_text()) current_playlist_name = file_list[k].name @@ -242,7 +254,18 @@ def action_loadPlaylist(): +def _loadPlaylist( filename ): + global currentPlayList, current_playlist_name, current_id + try: + playlistFile = Path(filename) + currentPlayList = json.loads(playlistFile.read_text()) + current_playlist_name = filename + current_id = 0 + _ok("Playlist loaded: {}\n".format(current_playlist_name)) + return True + except Exception as e: + _err("_loadPlaylist error when loading '{}':{}".format(filename,e)) @@ -353,13 +376,4 @@ def action_quit(): quit = inkey() if quit != "n": _kill(process) - sys.exit(1) - -environ = { -# "REDIS_IP" : "127.0.0.1", - "REDIS_IP" : "192.168.2.44", - "REDIS_PORT" : "6379", - "REDIS_KEY" : "/pl/0/0", - "REDIS_SCENE" : "0", - "REDIS_LASER" : "0" -} + sys.exit(1) \ No newline at end of file diff --git a/clitools/runner_midi.py b/clitools/runner_midi.py old mode 100644 new mode 100755 index ecf4956..979137b --- a/clitools/runner_midi.py +++ b/clitools/runner_midi.py @@ -1,12 +1,87 @@ #!/usr/bin/python3 -import sys -import os -import signal -import subprocess -import time -import tty,termios +import argparse import re -import json -from pathlib import Path +import redis import runner_lib as runner +import time + +novationRows = [ + [ 0, 1, 2, 3, 4, 5, 6, 7 ], + [ *range(16,24)], + [ *range(32,40)], + [ *range(48,56)] +] + +argsparser = argparse.ArgumentParser(description="Playlist midi") +argsparser.add_argument("playlist",help="JSON playlist file ",type=str) +argsparser.add_argument("-i","--ip",help="IP address of the Redis server ",default="127.0.0.1",type=str) +argsparser.add_argument("-r","--row",help="Row of Novation pad. Default:1 ",default=1,type=str) +argsparser.add_argument("-k","--key",help="Redis key to update",default="0",type=str) +argsparser.add_argument("-l","--laser",help="Laser number. Default:0 ",default=0,type=int) +argsparser.add_argument("-p","--port",help="Port of the Redis server ",default="6379",type=str) +argsparser.add_argument("-s","--scene",help="Laser scene. Default:0 ",default=0,type=int) +argsparser.add_argument("-v","--verbose",action="store_true",help="Verbose") +args = argsparser.parse_args() + +ip = args.ip +port = args.port +key = args.key +verbose=args.verbose +laser = args.laser +scene = args.scene +playlist = args.playlist +row = args.row - 1 +rowKeys = novationRows[row] + + + +# Subscriber + +r = redis.StrictRedis(host=ip, port=port, db=0) +p = r.pubsub() +p.subscribe('/midi/last_event') +runner._killBill() + +# Set Laser and scene +runner._setKey( laser = laser, scene = scene) + +# Load playlist +runner._loadPlaylist( playlist ) + +print("Loaded playlist : {}".format(runner.currentPlayList)) + + +runner.action_info() +runner.current_id = -1 +while True: + runner._killBill() + + message = p.get_message() + if message: + #runner._ok ("Subscriber: %s" % message['data']) + + + # b'/midi/noteon/0/19/127' + match = re.match(".*/([0-9]+)/[0-9]+",str(message['data'])) + if not match: + continue + key = int(match.group(1)) + + # Check if the event is for us + if key not in rowKeys: + print("key {} not in {} ".format(key,rowKeys)) + continue + + try: + command_id = rowKeys.index(key) + cmd = runner.currentPlayList[command_id] + + if command_id != runner.current_id : + runner._ok("Launching command #{}\n Previous was {}\n Cmd:{}".format(command_id,runner.current_id,cmd)) + runner.action_match(command_id) + runner.action_runCommand() + else : + runner._err("Not running {} : already running.".format(command_id)) + except Exception as e : + print("Woops.",e)