first running version :D
added threading added basic byte stream output added fading effect for layers disabled all prints removed asyncio based websocket handling changed websocket library
This commit is contained in:
parent
b426b42c77
commit
fc4cd6353b
@ -1,20 +1,38 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python3
|
||||||
# needed for websocket events
|
|
||||||
import websocket
|
import websocket
|
||||||
try:
|
try:
|
||||||
import thread
|
import thread
|
||||||
except ImportError:
|
except ImportError:
|
||||||
import _thread as thread
|
import _thread as thread
|
||||||
import threading
|
import threading
|
||||||
import time
|
from datetime import datetime
|
||||||
|
import time as time_
|
||||||
import json
|
import json
|
||||||
# needed for effect layer logic
|
|
||||||
import png
|
import png
|
||||||
import numpy as np
|
import numpy as np
|
||||||
# output
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
# get screen size from parameters
|
||||||
|
Nx = 80
|
||||||
|
try:
|
||||||
|
Nx = int(sys.argv[1])
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
Ny = 40
|
||||||
|
try:
|
||||||
|
Ny = int(sys.argv[2])
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# get input parameter
|
||||||
|
beatsaber_host = '127.0.0.1'
|
||||||
|
try:
|
||||||
|
beatsaber_host = int(sys.argv[3])
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class Layer:
|
class Layer:
|
||||||
def __init__(self, new_path):
|
def __init__(self, new_path):
|
||||||
@ -38,20 +56,45 @@ class Layer:
|
|||||||
self.layer_current_event_value = 0
|
self.layer_current_event_value = 0
|
||||||
self.layer_event_triggered = False
|
self.layer_event_triggered = False
|
||||||
self.animation_finished = True
|
self.animation_finished = True
|
||||||
self.animation_update_limit_ms = 25
|
self.animation_update_limit_ms = 1
|
||||||
self.animation_last_update_ms = int(round(time.time() * 1000))
|
self.animation_last_update_ms = self.millis()
|
||||||
self.animation_current_brightness = self.max_brightness
|
self.animation_current_brightness = self.max_brightness
|
||||||
# just debug stuff
|
# just debug stuff
|
||||||
# print("created layer for " + self.path)
|
# print("created layer for " + self.path)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
# print("next frame for " + self.path)
|
# print("next frame for " + self.path)
|
||||||
|
self.run_next_fade_color()
|
||||||
self.render_rgb_layer(
|
self.render_rgb_layer(
|
||||||
self.layer_buffer_current_color[0],
|
self.layer_buffer_current_color[0],
|
||||||
self.layer_buffer_current_color[1],
|
self.layer_buffer_current_color[1],
|
||||||
self.layer_buffer_current_color[2]
|
self.layer_buffer_current_color[2]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def millis(self):
|
||||||
|
dt = datetime.now()
|
||||||
|
millis = dt.microsecond / 1000
|
||||||
|
return int(round((time_.time() * 1000) + int(millis)))
|
||||||
|
|
||||||
|
def run_next_fade_color(self):
|
||||||
|
if not self.animation_finished and self.animation_current_brightness > 0:
|
||||||
|
current_millis = self.millis()
|
||||||
|
if current_millis - self.animation_last_update_ms >= self.animation_update_limit_ms:
|
||||||
|
# fade rgb values
|
||||||
|
self.animation_current_brightness -= 10
|
||||||
|
self.animation_last_update_ms = self.millis()
|
||||||
|
|
||||||
|
# set current layer color brightness to animation brightness
|
||||||
|
for i in range(0, 2):
|
||||||
|
self.layer_buffer_current_color[i] = self.get_new_color_value(
|
||||||
|
self.layer_buffer_current_color[i],
|
||||||
|
self.animation_current_brightness
|
||||||
|
)
|
||||||
|
elif self.animation_finished:
|
||||||
|
# if animation is finished, reset current fade brightness
|
||||||
|
self.animation_current_brightness = self.max_brightness
|
||||||
|
# print("animation finished!")
|
||||||
|
|
||||||
def trigger_event(self, event_value):
|
def trigger_event(self, event_value):
|
||||||
# print("new event " + self.path + " value: " + str(event_value))
|
# print("new event " + self.path + " value: " + str(event_value))
|
||||||
self.layer_event_triggered = True
|
self.layer_event_triggered = True
|
||||||
@ -68,44 +111,31 @@ class Layer:
|
|||||||
if self.layer_event_triggered:
|
if self.layer_event_triggered:
|
||||||
# if event_value == 0:
|
# if event_value == 0:
|
||||||
# print("Layer off!")
|
# print("Layer off!")
|
||||||
if 0 > event_value < 3:
|
if event_value == 1 or event_value == 2:
|
||||||
# static blue light
|
# static blue light
|
||||||
output_rgb_array[2] = self.max_brightness
|
output_rgb_array[2] = self.max_brightness
|
||||||
|
self.animation_finished = True
|
||||||
elif event_value == 3:
|
elif event_value == 3:
|
||||||
# fade blue light
|
# fade blue light
|
||||||
# reset current brightness of color for new animation
|
|
||||||
# self.animation_current_brightness = self.max_brightness
|
|
||||||
output_rgb_array[2] = self.max_brightness
|
output_rgb_array[2] = self.max_brightness
|
||||||
elif 4 > event_value < 6:
|
# reset current brightness of color for new animation
|
||||||
|
self.animation_current_brightness = self.max_brightness
|
||||||
|
self.animation_finished = False
|
||||||
|
# output_rgb_array[2] = self.max_brightness
|
||||||
|
elif event_value == 5 or event_value == 6:
|
||||||
# static red light
|
# static red light
|
||||||
output_rgb_array[0] = self.max_brightness
|
output_rgb_array[0] = self.max_brightness
|
||||||
|
self.animation_finished = True
|
||||||
elif event_value == 7:
|
elif event_value == 7:
|
||||||
# fade red light
|
# fade red light
|
||||||
# reset current brightness of color for new animation
|
|
||||||
# self.animation_current_brightness = self.max_brightness
|
|
||||||
output_rgb_array[0] = self.max_brightness
|
output_rgb_array[0] = self.max_brightness
|
||||||
|
# reset current brightness of color for new animation
|
||||||
|
self.animation_current_brightness = self.max_brightness
|
||||||
|
self.animation_finished = False
|
||||||
|
# output_rgb_array[0] = self.max_brightness
|
||||||
# elif event_value != 0 and event_value > 7:
|
# elif event_value != 0 and event_value > 7:
|
||||||
# print("unknown event effect value")
|
# print("unknown event effect value")
|
||||||
|
|
||||||
# if not self.animation_finished:
|
|
||||||
# if int(round(time.time() * 1000) / self.animation_last_update_ms) > self.animation_update_limit_ms:
|
|
||||||
# if event_value == 3:
|
|
||||||
# # fade blue light
|
|
||||||
# output_rgb_array[2] = self.get_new_color_value(
|
|
||||||
# output_rgb_array[2],
|
|
||||||
# self.animation_current_brightness
|
|
||||||
# )
|
|
||||||
# elif event_value == 7:
|
|
||||||
# # fade red light
|
|
||||||
# output_rgb_array[2] = self.get_new_color_value(
|
|
||||||
# output_rgb_array[0],
|
|
||||||
# self.animation_current_brightness
|
|
||||||
# )
|
|
||||||
# if self.animation_finished:
|
|
||||||
# if animation is finished, reset current fade brightness
|
|
||||||
# self.animation_current_brightness = self.max_brightness
|
|
||||||
# print("animation finished!")
|
|
||||||
|
|
||||||
return output_rgb_array
|
return output_rgb_array
|
||||||
|
|
||||||
# only used for debbuging
|
# only used for debbuging
|
||||||
@ -118,8 +148,6 @@ class Layer:
|
|||||||
# print(output_string)
|
# print(output_string)
|
||||||
|
|
||||||
def render_rgb_layer(self, r=0, g=0, b=0):
|
def render_rgb_layer(self, r=0, g=0, b=0):
|
||||||
# for testing
|
|
||||||
b = self.max_brightness
|
|
||||||
# reset layer buffer, step by number of color values (default 3, rgb)
|
# reset layer buffer, step by number of color values (default 3, rgb)
|
||||||
for i in range(0, self.rgb_buffer_length):
|
for i in range(0, self.rgb_buffer_length):
|
||||||
self.layer_buffer_array[i] = 0
|
self.layer_buffer_array[i] = 0
|
||||||
@ -156,6 +184,14 @@ class Layer:
|
|||||||
return output_array
|
return output_array
|
||||||
|
|
||||||
|
|
||||||
|
# create layer objects for the lights
|
||||||
|
layer_small = Layer('maps/small.png')
|
||||||
|
layer_middle = Layer('maps/middle.png')
|
||||||
|
layer_big = Layer('maps/big.png')
|
||||||
|
layer_left = Layer('maps/left.png')
|
||||||
|
layer_right = Layer('maps/right.png')
|
||||||
|
|
||||||
|
|
||||||
# ------------------------------------
|
# ------------------------------------
|
||||||
# Websocket event part start
|
# Websocket event part start
|
||||||
# ------------------------------------
|
# ------------------------------------
|
||||||
@ -215,7 +251,7 @@ def event_beat_map(event_object):
|
|||||||
def event_beat_map_parse(beatmap_event_object):
|
def event_beat_map_parse(beatmap_event_object):
|
||||||
event_type = beatmap_event_object["type"]
|
event_type = beatmap_event_object["type"]
|
||||||
event_value = beatmap_event_object["value"]
|
event_value = beatmap_event_object["value"]
|
||||||
if 0 < event_type < 5:
|
if event_type >= 0 and event_type < 5:
|
||||||
if event_type == 0:
|
if event_type == 0:
|
||||||
trigger_light_small(event_value)
|
trigger_light_small(event_value)
|
||||||
elif event_type == 1:
|
elif event_type == 1:
|
||||||
@ -270,7 +306,7 @@ def on_close(ws):
|
|||||||
def on_open(ws):
|
def on_open(ws):
|
||||||
def run(*args):
|
def run(*args):
|
||||||
while True:
|
while True:
|
||||||
time.sleep(1)
|
time_.sleep(1)
|
||||||
|
|
||||||
# print("websocket connected")
|
# print("websocket connected")
|
||||||
thread.start_new_thread(run, ())
|
thread.start_new_thread(run, ())
|
||||||
@ -280,19 +316,20 @@ def on_open(ws):
|
|||||||
# ------------------------------------
|
# ------------------------------------
|
||||||
|
|
||||||
|
|
||||||
buffer_length = 80 * 40 * 3
|
def get_higher_color_value(value1, value2):
|
||||||
|
new_value = value2
|
||||||
|
if value1 > value2:
|
||||||
|
new_value = value1
|
||||||
|
return new_value
|
||||||
|
|
||||||
|
|
||||||
def get_new_color_value(current_value, mapping_value):
|
buffer_length = Nx * Ny * 3
|
||||||
mapping_value_float = float(mapping_value / 255)
|
|
||||||
new_value = current_value * mapping_value_float
|
|
||||||
return round(new_value)
|
|
||||||
|
|
||||||
|
|
||||||
def merge_layer_arrays(layer_first, layer_second):
|
def merge_layer_arrays(layer_first, layer_second):
|
||||||
output_array = np.zeros(buffer_length, np.uint8)
|
output_array = np.zeros(buffer_length, np.uint8)
|
||||||
for idx in range(0, buffer_length):
|
for idx in range(0, buffer_length):
|
||||||
output_array[idx] = get_new_color_value(layer_first[idx], layer_second[idx])
|
output_array[idx] = get_higher_color_value(layer_first[idx], layer_second[idx])
|
||||||
return output_array
|
return output_array
|
||||||
|
|
||||||
|
|
||||||
@ -306,50 +343,23 @@ def get_merged_layers_array():
|
|||||||
return output_array
|
return output_array
|
||||||
|
|
||||||
|
|
||||||
def loop_layers():
|
# Start websocket logic thread
|
||||||
# print("start layers loop")
|
ws = websocket.WebSocketApp('ws://' + beatsaber_host + ':6557/socket',
|
||||||
time_ms = 10
|
|
||||||
t = 0
|
|
||||||
# main frame render loop
|
|
||||||
while True:
|
|
||||||
t += time_ms / 1000.0
|
|
||||||
# layer_small.run()
|
|
||||||
# layer_middle.run()
|
|
||||||
# layer_big.run()
|
|
||||||
# layer_left.run()
|
|
||||||
# layer_right.run()
|
|
||||||
# output_buffer = get_merged_layers_array()
|
|
||||||
# output_bytes = output_buffer.tobytes()
|
|
||||||
|
|
||||||
layer_middle.run()
|
|
||||||
layer_middle_frame = layer_middle.get_next_frame()
|
|
||||||
output_bytes = layer_middle_frame.tobytes()
|
|
||||||
# print(sys.getsizeof(output_bytes))
|
|
||||||
# print("new frame:")
|
|
||||||
# print(output_bytes)
|
|
||||||
os.write(1, output_bytes)
|
|
||||||
|
|
||||||
# warte time_ms ms
|
|
||||||
time.sleep(time_ms * 0.001)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
layer_small = Layer('maps/small.png')
|
|
||||||
layer_middle = Layer('maps/middle.png')
|
|
||||||
layer_big = Layer('maps/big.png')
|
|
||||||
layer_left = Layer('maps/left.png')
|
|
||||||
layer_right = Layer('maps/right.png')
|
|
||||||
|
|
||||||
# Start websocket logic thread
|
|
||||||
# websocket.enableTrace(True)
|
|
||||||
ws = websocket.WebSocketApp('ws://127.0.0.1:6557/socket',
|
|
||||||
on_message=on_message,
|
on_message=on_message,
|
||||||
on_error=on_error,
|
on_error=on_error,
|
||||||
on_close=on_close)
|
on_close=on_close)
|
||||||
ws.on_open = on_open
|
ws.on_open = on_open
|
||||||
wst = threading.Thread(target=ws.run_forever)
|
wst = threading.Thread(target=ws.run_forever)
|
||||||
wst.daemon = True
|
wst.daemon = True
|
||||||
wst.start()
|
wst.start()
|
||||||
|
|
||||||
# Start layer logic thread
|
# Start layer logic loop
|
||||||
loop_layers()
|
while True:
|
||||||
|
layer_small.run()
|
||||||
|
layer_middle.run()
|
||||||
|
layer_big.run()
|
||||||
|
layer_left.run()
|
||||||
|
layer_right.run()
|
||||||
|
output_buffer = get_merged_layers_array()
|
||||||
|
output_bytes = output_buffer.tobytes()
|
||||||
|
os.write(1, output_bytes)
|
Loading…
Reference in New Issue
Block a user