cdosea-play/cdoseaplay/lights.py

166 lines
4.4 KiB
Python
Raw Normal View History

2017-08-29 17:27:06 +00:00
#!/usr/bin/python3
2023-12-19 13:26:25 +00:00
import os
import string
2017-08-29 17:27:06 +00:00
import subprocess
import sys
import time
import ox
2023-10-06 22:21:26 +00:00
import sacn
2017-10-16 18:31:44 +00:00
from .pi import random
2023-10-06 22:21:26 +00:00
from . import config
2017-10-16 18:31:44 +00:00
# Screen 1-5, Control, 6,7
'''
2024-01-22 09:03:48 +00:00
>
_*10 patterns / cues that correspond to 10 digit:*_
0 = Cue list 1 = 1x flash (on, off)
1 = Cue list 2 = 2x flashes (on, off, on, off)
2 = Cue list 3 = 3x flashes (on, off, on, off, on, off)
...and so on...
8 = Cue list 9 = 9x flashes
9 = Cue list 10 = 10x flashes
The basic timing for 1x flash is:
- Flash on over 0s
- Hold on for 0.2s
- Flash off over 0s
- Hold off for 0.2s
2017-10-16 18:31:44 +00:00
'''
def channels(screen, control):
screen = int(screen * 255)
control = int(control * 255)
return {'1': screen, '2': screen, '3': screen, '4': screen, '5': screen, '6': control, '7': control}
LIGHTS = {
0: (channels(1, 0.0), 9),
1: (channels(0, 0.1), 8),
2: (channels(0, 0.2), 7),
3: (channels(0, 0.3), 6),
4: (channels(0, 0.4), 5),
5: (channels(0, 0.5), 4),
6: (channels(0, 0.6), 3),
7: (channels(0, 0.7), 2),
8: (channels(0, 0.8), 1),
9: (channels(0, 0.9), 0.1),
}
2024-01-15 11:55:05 +00:00
2023-10-06 22:21:26 +00:00
CURRENT_STATE = [0] * 16
2024-01-22 09:03:48 +00:00
# avoid overload and turn light on with a fade
2024-06-17 15:49:55 +00:00
def fade_to(sender, start, end, duration, channels=16, universe=1, lights=[]):
2024-01-22 09:03:48 +00:00
distance = end - start
2023-10-06 22:21:26 +00:00
steps = int(duration * 10)
2024-01-22 09:03:48 +00:00
if not steps:
steps = 2
2023-10-06 22:21:26 +00:00
step = duration/steps
delta = distance/steps
2024-01-22 09:03:48 +00:00
current = start
2023-10-06 22:21:26 +00:00
value = current
switch = 0
2023-10-06 22:21:26 +00:00
while steps:
switch += 1
2023-10-06 22:21:26 +00:00
value += delta
n = int(round(value))
if n != current:
current = n
2024-01-22 09:03:48 +00:00
old = sender[1].dmx_data[:channels]
target = [n] * channels
if switch % 2:
a = target
b = old
else:
a = old
b = target
2024-06-17 15:49:55 +00:00
channel_data = [a[x] if x % 2 else b[x] for x in range(channels)]
sender[universe].dmx_data = channel_data + lights[channels:]
2023-10-06 22:21:26 +00:00
time.sleep(step)
steps -= 1
2024-06-17 15:49:55 +00:00
channel_data = [end] * channels
sender[universe].dmx_data = channel_data + lights[channels:]
2023-10-06 22:21:26 +00:00
2024-06-17 15:49:55 +00:00
def dmx_base(letter):
lights = [0] * 512
letter_offset = 101 - 1
for offset in range(letter_offset, letter_offset+27):
lights[offset] = config.letter_base_light
if letter:
lights[letter_offset + string.ascii_lowercase.index(letter.lower())] = 255
lights[letter_offset + 26] = 255
return lights
2023-10-06 22:21:26 +00:00
2024-06-17 15:49:55 +00:00
def flash(sender, universe, flashes, letter):
2024-01-22 09:03:48 +00:00
step = 0.2
flash_duration = 0.02
base = 0
brightness = config.lights_brightness
2024-06-17 15:49:55 +00:00
channels = config.led_lights
2024-01-22 09:03:48 +00:00
sender[universe].dmx_data = [0] * channels
2024-01-15 11:55:05 +00:00
while flashes:
2024-06-17 15:49:55 +00:00
lights = dmx_base(letter)
fade_to(sender, base, brightness, flash_duration, channels, universe, lights)
2024-01-22 09:03:48 +00:00
time.sleep(step)
2024-06-17 15:49:55 +00:00
lights = dmx_base(None)
channel_data = [0] * channels
sender[universe].dmx_data = channel_data + lights[channels:]
2024-01-15 11:55:05 +00:00
time.sleep(step)
flashes -= 1
2024-06-17 15:49:55 +00:00
lights = dmx_base(None)
channel_data = [0] * channels
sender[universe].dmx_data = channel_data + lights[channels:]
2024-01-22 09:03:48 +00:00
time.sleep(step)
2024-01-15 11:55:05 +00:00
def switch(state, seq):
2024-01-22 09:03:48 +00:00
import lanbox
lb = lanbox.Lanbox()
lb.layerGo(state)
2024-01-15 11:55:05 +00:00
2017-10-16 18:31:44 +00:00
if __name__ == '__main__':
path = sys.argv[1]
2023-12-19 13:26:25 +00:00
no_sleep = len(sys.argv) > 2 and sys.argv[2] == "no-sleep"
2017-10-16 18:31:44 +00:00
2023-12-19 13:26:25 +00:00
n = int(os.path.getctime(path) - 1495280000) % 1000
2017-10-16 18:31:44 +00:00
info = ox.avinfo(path)
duration = info.get('duration', 0)
2023-12-19 13:26:25 +00:00
seq = random(n * 100)
2017-10-16 18:31:44 +00:00
pos = 0
lights = []
2023-12-19 13:26:25 +00:00
letter_offset = 0
2024-01-03 09:12:35 +00:00
letter = path.split('/')[-1][0].lower()
2023-12-19 13:26:25 +00:00
if config.letter_offset:
2024-06-17 15:49:55 +00:00
if config.lanbox:
letter_offset = 11 + string.ascii_lowercase.index(letter) * 10
if not config.lanbox:
universe = 1
sender = sacn.sACNsender()
sender.start()
sender.activate_output(universe)
sender[universe].multicast = True
2017-10-16 18:31:44 +00:00
while pos < duration - 15:
sleep = seq() + 15
light = seq()
if pos + sleep > duration:
break
2017-10-16 19:31:13 +00:00
if not no_sleep:
time.sleep(sleep)
2024-07-03 15:00:30 +00:00
print("letter", letter, "offset", letter_offset, "light", light, "cue", letter_offset + light, "sleep", sleep)
2024-01-22 09:03:48 +00:00
if config.lanbox:
switch(light + letter_offset, seq)
else:
2024-06-17 15:49:55 +00:00
flash(sender, universe, light + 1, letter)
2017-10-16 18:31:44 +00:00
pos += sleep
2024-06-17 15:49:55 +00:00
if not config.lanbox:
sender.stop()