LJ/clitools/runner_lib.py

379 lines
8.4 KiB
Python
Raw Normal View History

import sys
import os
import signal
import subprocess
import time
import tty,termios
import re
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'
OKGREEN = '\033[92m'
ENDC = '\033[0m'
BOLD = '\033[1m'
UNDERLINE = '\033[4m'
class _Getch:
def __call__(self):
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
tty.setraw(sys.stdin.fileno())
ch = sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
return ch
inkey = _Getch()
def intkey():
try:
i = int( inkey() )
return(i)
except ValueError:
print("Error.")
current_id = 0
current_cmd = ""
process = None
current_filename = ""
currentPlayList = []
playlistsDir = Path("./playlists")
if not playlistsDir.is_dir() : playlistsDir.mkdir()
def ask(q):
print(q)
return inkey()
def _ok(msg):
print( bcolors.BOLD+bcolors.OKBLUE+ msg + bcolors.ENDC)
def _err(msg):
print( bcolors.HL + msg + bcolors.ENDC)
def _kill(process):
if process :
try:
pid = os.getpgid(process.pid)
os.killpg(pid, signal.SIGTERM)
os.killpg(pid, signal.SIGKILL)
os.kill(pid, signal.SIGTERM)
os.kill(pid, signal.SIGKILL)
process.terminate()
process.kill()
except Exception as e:
print("woops:{}".format(e))
def _killBill():
subprocess.run("ps --ppid 1 -fo pid,sess,ppid,cmd | grep 'toRedis.py' | while read pid sid other; do pkill -9 -s $sid; done", shell=True,executable='/bin/bash')
def action_info():
print("""
Welcome to LJ playlist manager
Currently running on
IP : {}
Port : {}
Key : {}
Scene : {}
Laser : {}
""".format(
environ["REDIS_IP"],
environ["REDIS_PORT"],
environ["REDIS_KEY"],
environ["REDIS_SCENE"],
environ["REDIS_LASER"]
))
def action_changeCommand( inc ):
global currentPlayList
global current_id
if 0 == len(currentPlayList):
_err("Empty playlist")
return False
current_id = (current_id + 1) % len(currentPlayList)
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():
global currentPlayList
global current_id
global process
# Get new command
try:
current_cmd = currentPlayList[current_id]
except IndexError as e:
_err("woops:{}".format(e))
return False
print("\n[!]New command:'{}'\n".format(current_cmd))
# Start subprocess
try :
_kill(process)
process = subprocess.Popen("./_run.sh '"+current_cmd+" | exports/toRedis.py -i $REDIS_IP -k $REDIS_KEY'", shell=True, executable='/bin/bash', stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, env=environ, preexec_fn=os.setsid)
except Exception as e:
print("woops:{}".format(e))
def action_newCommand():
global currentPlayList
print("Enter new command or e(x)it.")
k = input()
# Exit early
if "x" == k:
return(False)
currentPlayList.append(k)
print(bcolors.OKBLUE + "Command added" + bcolors.ENDC)
return True
def action_deleteCommand():
global currentPlayList
print("Select sequence to delete or e(x)it.")
action_listAll()
key = int(input())
# Exit early
if "x" == key:
return(False)
del currentPlayList[key]
return True
def action_listAll():
global currentPlayList, current_cmd, current_id
print("\n--------------------------------------")
for i,seq in enumerate(currentPlayList):
pre=""
suf=""
if current_cmd == seq :
pre = bcolors.HL
suf = bcolors.ENDC
print( pre + "{}\t{}".format(i,seq) + suf )
print("--------------------------------------\n")
def action_edit():
print("Enter the command number to edit, or 'x' to abort.")
k = intkey()
if 'x' == k:
return
print("Enter the next value, or 'x' to abort.")
value = input()
if 'x' == value:
return
currentPlayList[k] = value
def action_loadPlaylist():
global playlistsDir
global currentPlayList
global current_playlist_name
# list files
i=0
file_list = [x for x in playlistsDir.glob("*json")]
if 0 == len(file_list ):
print( bcolors.HL + "Error. No file in path '{}'\n".format(playlistsDir.name))
return False
print("\n Id\tName")
for k,name in enumerate(file_list) :
print(" {}\t{}".format(k,name),flush=True)
# ask file
print("\nChoose a file or e(x)it:")
k = intkey()
if '' == k:
print("Invalid choice: '{}'".format(k))
return
# Exit early
if "x" == k: return(False)
# todo : helper for detecting invalid keys
try:
if k > (len(file_list) - 1):
print( bcolors.HL + "This key '{}' does not exist".format(k) + bcolors.ENDC )
return False
except TypeError:
print( bcolors.HL + "This key '{}' is not valid".format(k) + bcolors.ENDC )
return False
# @todo replace with _loadPlaylist
playlistFile = Path("./playlists/"+file_list[k].name)
currentPlayList = json.loads(playlistFile.read_text())
current_playlist_name = file_list[k].name
current_id = 0
print( bcolors.OKBLUE + "Playlist loaded: {}\n".format(current_playlist_name)+ bcolors.ENDC)
return True
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))
def action_newPlaylist():
global playlistsDir
global currentPlayList
# ask for name
print("Enter new playlist name (without.json) or e(x)it question?")
k = input()
# Exit early
if "x" == k:
return(False)
# save file
currentPlayList = []
_savePlaylist( k+".json" )
currentPlayList = []
pass
def _savePlaylist( playlistname ):
global currentPlayList
filepath = Path("playlists/{}".format(playlistname))
with filepath.open("w", encoding ="utf-8") as f:
f.write(json.dumps(currentPlayList, indent=4, sort_keys=True))
return(True)
def action_savePlaylist( name=False ):
global current_playlist_name
playlist_name = name if name else current_playlist_name
if not playlist_name :
_err("No name found.")
return False
try:
_savePlaylist(playlist_name)
print( bcolors.OKBLUE + "\nSaved as '{}'.\n".format(playlist_name) + bcolors.ENDC)
except Exception as e:
print("woops:{}".format(e))
return False
def action_commandHelp():
global playlistsDir
# iterate through files
file_list=[]
for folder in ["generators","filters","exports"]:
p = Path("./"+folder)
for plFile in Path("./"+folder).iterdir() :
if re.match("^.*py$",plFile.name):
file_list.append(os.path.join(folder,plFile.name))
print("\n Id\tFile")
for k,filename in enumerate(file_list):
print(" {}\t{}".format(k,filename))
print("\nChoose a file:")
k = int(input())
print("\n-----------------------------------------------\n")
subprocess.run("python3 "+file_list[k]+" -h", shell=True, executable='/bin/bash')
print("\n-----------------------------------------------\n")
def _setKey( laser=0, scene=0 ):
global environ
laser = laser if laser else environ["REDIS_LASER"]
scene = scene if scene else environ["REDIS_SCENE"]
new_key = "/pl/{}/{}".format(scene,laser)
environ["REDIS_KEY"] = new_key
print("Sending new key '{}'".format(new_key))
def action_laserId():
k = int(ask("Enter the LJ Laser id [0-3]"))
_setKey( laser = k )
def action_laserScene():
k = int(ask("Enter the LJ Scene id [0-3]"))
_setKey( scene = k )
def action_killPid():
print("Enter pid to kill")
kill_pid = input()
subprocess.run("pkill -9 -s $(awk '{print $6}' /proc/$kill_pid/stat)", shell=True,executable='/bin/bash', env={"kill_pid":kill_pid})
def action_quit():
print("Quit [Y/n]?")
2020-10-09 16:33:32 +00:00
global process
quit = inkey()
if quit != "n":
_kill(process)
sys.exit(1)