156 lines
4.0 KiB
Python
156 lines
4.0 KiB
Python
# events.py
|
|
|
|
import soundfile
|
|
import sounddevice
|
|
|
|
import timings
|
|
import display
|
|
|
|
import numpy as np
|
|
|
|
class Event:
|
|
def __init__(self, at='start'):
|
|
self._at = timings.Timing(at)
|
|
|
|
def set_timings(self, timings):
|
|
self._at.set_timings(timings)
|
|
|
|
def set_audiencecontent(self, audiencecontent):
|
|
self.audiencecontent = audiencecontent
|
|
|
|
@property
|
|
def scheduled(self):
|
|
return self._at.scheduled
|
|
|
|
@scheduled.setter
|
|
def scheduled(self, value):
|
|
self._at.scheduled = value
|
|
|
|
@property
|
|
def at(self):
|
|
return self._at.at
|
|
|
|
def prepare(self):
|
|
pass
|
|
|
|
def start(self):
|
|
pass
|
|
|
|
def stop(self):
|
|
pass
|
|
|
|
class Display(Event):
|
|
def __init__(self, media, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
self._media = media
|
|
|
|
|
|
class Playback(Event):
|
|
def __init__(self, media, device=None, channels=[1,2], tempo=None, beats=None, leadin=0, loop=False, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
self._media = media
|
|
self._device = device
|
|
self._mapping = np.atleast_1d(np.array(channels, copy=True))
|
|
self._channels = self._mapping.max()
|
|
self._mapping -= 1
|
|
self._tempo = tempo
|
|
self._beats = beats
|
|
self._leadin = leadin
|
|
self._loop = loop
|
|
|
|
def prepare(self):
|
|
self._at._timings.register_tempo(self._tempo, self._beats, self._at)
|
|
|
|
# def start(self):
|
|
# print("Start playback")
|
|
# data, fs = soundfile.read(self._media)
|
|
# sounddevice.play(data, fs, device=self._device, mapping=self._mapping)
|
|
|
|
def start(self):
|
|
print("Start playback")
|
|
self._data, fs = soundfile.read(self._media)
|
|
self._current_frame = 0
|
|
|
|
self._stream = sounddevice.OutputStream(
|
|
samplerate=fs, device=self._device, channels=self._channels,
|
|
callback=self.callback, finished_callback=self.finished_callback)
|
|
self._stream.start()
|
|
|
|
def callback(self, outdata, frames, time, status):
|
|
if status:
|
|
print(status)
|
|
chunksize = min(len(self._data) - self._current_frame, frames)
|
|
outdata[:chunksize, self._mapping] = self._data[self._current_frame:self._current_frame + chunksize]
|
|
if chunksize < frames:
|
|
outdata[chunksize:, self._mapping] = 0
|
|
raise sounddevice.CallbackStop()
|
|
self._current_frame += chunksize
|
|
|
|
def finished_callback(self):
|
|
self._data = None
|
|
print("Playback finished")
|
|
|
|
def stop(self):
|
|
print("Stop playback")
|
|
self._stream.stop(True)
|
|
self._stream.close(True)
|
|
self._stream = None
|
|
|
|
class SetTempo(Event):
|
|
def __init__(self, tempo=None, beats=None, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
self._tempo = tempo
|
|
self._beats = beats
|
|
|
|
def prepare(self):
|
|
self._at._timings.register_tempo(self._tempo, self._beats, self._at)
|
|
|
|
def start(self):
|
|
pass
|
|
|
|
def stop(self):
|
|
pass
|
|
|
|
class SetMark(Event):
|
|
def __init__(self, name, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
self._name = name
|
|
|
|
def prepare(self):
|
|
self._at._timings.register_mark(self._name, self._at)
|
|
|
|
def start(self):
|
|
pass
|
|
|
|
def stop(self):
|
|
pass
|
|
|
|
class ButtonMark(Event):
|
|
def __init__(self, name, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
self._name = name
|
|
|
|
def prepare(self):
|
|
self._at._timings.register_mark(self._name, None)
|
|
|
|
def start(self):
|
|
pass
|
|
|
|
def stop(self):
|
|
pass
|
|
|
|
class Lyrics(Event):
|
|
def __init__(self, text, duration=None, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
self._text = text
|
|
self._duration = duration
|
|
|
|
def start(self):
|
|
self.audiencecontent.new_content(display.DisplayLyrics(self._text))
|
|
print("Started displaying lyrics")
|
|
print(self._text)
|
|
|
|
def stop(self):
|
|
self.audiencecontent.new_content(display.DisplayContent())
|
|
print("Stopped displaying lyrics")
|