def build(self): vbodata = [] idxdata = [] for i,g in enumerate(self.line.glyphs): if get_opts().instant: tleft = tright = g.t1 else: tleft = map_to(map_from(g.x + g.glyph.left, g.tx1, g.tx2), g.t1, g.t2) tright = map_to(map_from(g.x + g.glyph.right, g.tx1, g.tx2), g.t1, g.t2) const_vbodata = [self.line.start, self.line.end] const_vbodata += list(i/255.0 for i in sum(g.colors + g.colors_on, ())) vbodata.append( [g.x + g.glyph.left, g.y + g.glyph.bot, g.glyph.tex_left, g.glyph.tex_bot, tleft] + const_vbodata) vbodata.append( [g.x + g.glyph.left, g.y + g.glyph.top, g.glyph.tex_left, g.glyph.tex_top, tleft] + const_vbodata) vbodata.append( [g.x + g.glyph.right, g.y + g.glyph.top, g.glyph.tex_right, g.glyph.tex_top, tright] + const_vbodata) vbodata.append( [g.x + g.glyph.right, g.y + g.glyph.bot, g.glyph.tex_right, g.glyph.tex_bot, tright] + const_vbodata) idxdata += (i*4, i*4+1, i*4+2, i*4+2, i*4+3, i*4) self.vbo = vbo.VBO(np.asarray(vbodata, np.float32), gl.GL_STATIC_DRAW, gl.GL_ARRAY_BUFFER) self.ibo = vbo.VBO(np.asarray(idxdata, np.uint16), gl.GL_STATIC_DRAW, gl.GL_ELEMENT_ARRAY_BUFFER) self.count = len(self.line.glyphs)
def __init__(self, display): self.last_audio_reconfig = 0 self.audio_reconfig_pending = False self.volume = 0.5 self.song = None self.display = display self.opts = opts = util.get_opts() self.mpv = mpv.Context() self.gl = None self.mpv.initialize() if opts.mpv_msg_level: self.mpv.set_property("msg-level", opts.mpv_msg_level) self.mpv.set_property("audio-file-auto", "no") self.mpv.set_property("terminal", True) self.mpv.set_property("quiet", True) if opts.mpv_ao: self.mpv.set_property("ao", opts.mpv_ao) elif opts.mpv_audio_device: self.mpv.set_property("audio-device", opts.mpv_audio_device) self.mpv.set_property("fs", True) if opts.mpv_ao == "jack": self.mpv.set_property("jack-autostart", "yes") self.mpv.set_property( "af", '@lavfi:lavfi="pan=stereo|c0=c0|c1=c1",@rb:rubberband=pitch=speed') if opts.mpv_options: for opt in shlex.split(opts.mpv_options): if "=" not in opt: key, val = opt, True else: key, val = opt.split("=", 1) self.mpv.set_property(key, val) self.poll_props = {"audio-pts": None} for i in self.poll_props: self.mpv.get_property_async(i) if display: if opts.mpv_hwdec: self.mpv.set_property("hwdec", opts.mpv_hwdec) vo = opts.mpv_vo if vo in ("opengl-cb", "libmpv"): vo = "libmpv" self.mpv.set_property("video-sync", "display-vdrop") self.mpv.set_property("display-fps", display.fps or opts.fps) def gpa(name): return display.get_proc_address(name) self.gl = mpv.OpenGLRenderContext(self.mpv, gpa, **display.get_mpv_params()) else: self.gl = None self.mpv.set_property("vo", vo) self.solid_renderer = graphics.get_solid_renderer() else: self.gl = None self.mpv.set_property("vo", "null") self.mpv.set_property("vid", "no")
def Display(*args, **kwargs): global _display display = util.get_opts().display if display == "glut": from blitzloop.backend import glut _display = glut.Display(*args, **kwargs) elif display == "rpi": from blitzloop.backend import rpi _display = rpi.Display(*args, **kwargs) return _display
def __init__(self, display): self.last_audio_reconfig = 0 self.audio_reconfig_pending = False self.volume = 0.5 self.song = None self.display = display self.opts = opts = util.get_opts() self.mpv = mpv.Context() self.gl = None self.mpv.initialize() if opts.mpv_msg_level: self.mpv.set_property("msg-level", opts.mpv_msg_level) self.mpv.set_property("audio-file-auto", "no") self.mpv.set_property("terminal", True) self.mpv.set_property("quiet", True) if opts.mpv_ao: self.mpv.set_property("ao", opts.mpv_ao) elif opts.mpv_audio_device: self.mpv.set_property("audio-device", opts.mpv_audio_device) self.mpv.set_property("fs", True) if opts.mpv_ao == "jack": self.mpv.set_property("jack-autostart", "yes") self.mpv.set_property("af", '@lavfi:lavfi="pan=stereo|c0=c0|c1=c1",@rb:rubberband=pitch=speed') if opts.mpv_options: for opt in shlex.split(opts.mpv_options): if "=" not in opt: key, val = opt, True else: key, val = opt.split("=", 1) self.mpv.set_property(key, val) self.poll_props = {"audio-pts": None} for i in self.poll_props: self.mpv.get_property_async(i) if display: if opts.mpv_hwdec: self.mpv.set_property("hwdec", opts.mpv_hwdec) vo = opts.mpv_vo if vo in ("opengl-cb", "libmpv"): vo = "libmpv" self.mpv.set_property("video-sync", "display-vdrop") self.mpv.set_property("display-fps", display.fps or opts.fps) def gpa(name): return display.get_proc_address(name) self.gl = mpv.OpenGLRenderContext(self.mpv, gpa, **display.get_mpv_params()) else: self.gl = None self.mpv.set_property("vo", vo) self.solid_renderer = graphics.get_solid_renderer() else: self.gl = None self.mpv.set_property("vo", "null") self.mpv.set_property("vid", "no")
def toggle_fullscreen(self): if self.fullscreen: glfw.set_window_monitor(self.window, None, *self.saved_size, util.get_opts().fps) else: self.saved_size = self.x, self.y, self.win_width, self.win_height monitor = glfw.get_primary_monitor() mode = glfw.get_video_mode(monitor) glfw.set_window_monitor(self.window, monitor, 0, 0, mode.size.width, mode.size.height, mode.refresh_rate) self.fullscreen = not self.fullscreen
def toggle_fullscreen(self): if self.fullscreen: glfw.set_window_monitor(self.window, None, *self.saved_size, util.get_opts().fps) else: self.saved_size = self.x, self.y, self.win_width, self.win_height monitor = glfw.get_primary_monitor() mode = glfw.get_video_mode(monitor) glfw.set_window_monitor(self.window, monitor, 0, 0, mode.size.width, mode.size.height, mode.refresh_rate) self.fullscreen = not self.fullscreen
def Display(*args, **kwargs): global _display display = util.get_opts().display if display == "glut": from blitzloop.backend import glut _display = glut.Display(*args, **kwargs) elif display == "glfw": from blitzloop.backend import glfw _display = glfw.Display(*args, **kwargs) elif display == "rpi": from blitzloop.backend import rpi _display = rpi.Display(*args, **kwargs) elif display == "kms": from blitzloop.backend import kms _display = kms.Display(*args, **kwargs) else: raise Exception("Unknown display: %s" % display) return _display
def __init__(self, display): self.volume = 0.5 self.song = None self.display = display opts = util.get_opts() self.mpv = mpv.Context() self.mpv.initialize() self.mpv.set_property("audio-file-auto", "no") self.mpv.set_property("terminal", True) self.mpv.set_property("quiet", True) self.mpv.set_property("ao", opts.mpv_ao) self.mpv.set_property("fs", True) if opts.mpv_ao == "jack": self.mpv.set_property("jack-autostart", "yes") self.mpv.set_property("af", "@pan:pan=2:[1,0,0,1],@rb:rubberband") for optval in opts.mpv_options.split(): opt, val = optval.split("=", 1) self.mpv.set_property(opt, val) self.poll_props = {"audio-pts": None} for i in self.poll_props: self.mpv.get_property_async(i) if display: if opts.mpv_vo == "opengl-cb": self.mpv.set_property("video-sync", "display-vdrop") self.mpv.set_property("display-fps", opts.fps) def gpa(name): return display.get_proc_address(name) self.gl = self.mpv.opengl_cb_api() self.gl.init_gl(None, gpa) else: self.gl = None self.mpv.set_property("vo", opts.mpv_vo) self.solid_renderer = graphics.get_solid_renderer() else: self.gl = None self.mpv.set_property("vo", "null") self.mpv.set_property("vid", "no")
# # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA import numpy as np import PIL from OpenGL import arrays from OpenGL.arrays import vbo from blitzloop import texture_font from blitzloop.util import map_from, map_to, get_opts from blitzloop.matrix import Matrix if get_opts().display in ("glut", ): import OpenGL.GL as gl import OpenGL.GL.shaders as shaders import OpenGL.GLU as glu else: import OpenGL.GLES2 as gl import OpenGL.GLES2.shaders as shaders glu = None vs_karaoke = """ attribute vec4 coords; attribute vec3 border_color; attribute vec3 fill_color; attribute vec3 outline_color; attribute vec3 border_color_on;
def entry(): data_home = os.getenv('XDG_DATA_HOME', '~/.local/share') songs_dir = os.path.join(data_home, 'blitzloop', 'songs') def csv_list(s): return s.split(",") parser = util.get_argparser() parser.add_argument( '--songdir', default=os.path.expanduser(songs_dir), help='directory with songs') parser.add_argument('--host', default='0.0.0.0', help='IP to listen on') parser.add_argument( '--port', default=10111, type=int, help='port for the UI') parser.add_argument( '--width', type=int, default=1024, help='width of blitzloop window (ignored in fs)') parser.add_argument( '--height', type=int, default=768, help='height of blitzloop window (ignored in fs)') parser.add_argument( '--no-audioengine', action="store_true", help='Disable JACK-based audio engine (mic echo effect)') parser.add_argument( '--mics', type=csv_list, default=["system:capture_1"], help='Mic input connections (list of JACK ports)') opts = util.get_opts() songs_dir = os.path.expanduser(opts.songdir) print("Loading song DB...") song_database = songlist.SongDatabase(songs_dir) print("Done.") display = graphics.Display(opts.width, opts.height, opts.fullscreen) renderer = graphics.get_renderer().KaraokeRenderer(display) mpv = mpvplayer.Player(display) if not opts.no_audioengine and opts.mics: from blitzloop._audio import AudioEngine print(repr(opts.mics)) audio = AudioEngine([s.encode("ascii") for s in opts.mics]) print("Engine sample rate: %dHz" % audio.sample_rate) queue = songlist.SongQueue() class AudioConfig(object): def __init__(self): self.nmics = len(opts.mics) if not opts.no_audioengine else 0 self.volume = 80 if opts.no_audioengine: self.mic_channels = [] else: self.mic_channels = [{"volume": 80} for i in range(self.nmics)] self.mic_feedback = 20 self.mic_delay = 12 self.headstart = 30 def update(self, song=None): mpv.set_volume(((self.volume / 100.0) ** 2) * 0.5) if not opts.no_audioengine: for i, j in enumerate(self.mic_channels): audio.set_mic_volume(i, ((j["volume"] / 100.0) ** 2) * 2.0) audio.set_mic_feedback(self.mic_feedback / 100.0) audio.set_mic_delay(self.mic_delay / 100.0) audio_config = AudioConfig() web.database = song_database web.queue = queue web.audio_config = audio_config server = web.ServerThread(host=opts.host, port=opts.port) server.start() idle_screen = idlescreen.IdleScreen(display) def main_render(): # Wait for element in queue print("Waiting for song to appear in queue...") qe = None with queue.lock: if len(queue) != 0: qe = queue[0] if not qe: idle_screen.reset() graphics.get_renderer().clear(0, 0, 0, 1) for f in idle_screen: audio_config.update() yield None graphics.get_renderer().clear(0, 0, 0, 1) if not qe: with queue.lock: if len(queue) != 0: qe = queue[0] idle_screen.close() for i in range(2): yield None graphics.get_renderer().clear(0, 0, 0, 1) print("Loading audio/video...") mpv.load_song(qe.song) display.set_aspect(mpv.aspect) def update_params(defer=False): mpv.set_speed(1.0 / (2**(qe.speed / 12.0))) mpv.set_pitch(2**(qe.pitch / 12.0)) for i, j in enumerate(qe.channels): mpv.set_channel(i, j["volume"] / 10., defer=defer) mpv.set_pause(qe.pause) update_params(True) mpv.update_mixer(force=True) print("Laying out song...") renderer.reset() variant_key = list(qe.song.variants.keys())[qe.variant] song_layout = layout.SongLayout(qe.song, variant_key, renderer) print("Loaded.") song_time = -10 stopping = False while not (mpv.eof_reached() or (stopping and qe.pause)): while qe.commands: cmd, arg = qe.commands.pop(0) if cmd == "seek": mpv.seek(arg) elif cmd == "seekto": mpv.seek_to(arg) mpv.draw() mpv.poll() song_time = mpv.get_song_time() or song_time if qe.stop and not stopping: stopping = True mpv.fade_out = 2 mpv.duration = min(mpv.duration, song_time + 2) if not stopping: mpv.draw_fade(song_time) speed = 2**(qe.speed / 12.0) renderer.draw(song_time + audio_config.headstart / 100.0 * speed, song_layout) if stopping: fade = mpv.draw_fade(song_time) mpv.set_fadevol(max(fade * 1.3 - 0.3, 0)) update_params() audio_config.update(qe.song) yield None mpv.flip() graphics.get_renderer().clear(0, 0, 0, 1) for i in range(2): yield None graphics.get_renderer().clear(0, 0, 0, 1) print("Song complete.") del song_layout try: queue.pop(qe.qid) except (IndexError, KeyError): pass mpv.stop() display.set_aspect(None) def main(): while True: for i in main_render(): yield i def exit(): print("Exit handler called") mpv.shutdown() if not opts.no_audioengine: audio.shutdown() server.stop() print("Exit handler done") def key(k): if k == 'KEY_ESCAPE': display.queue_exit() elif k == 'f': display.toggle_fullscreen() display.set_render_gen(main) display.set_keyboard_handler(key) display.set_exit_handler(exit) display.main_loop() threads = threading.enumerate() if len(threads) > 1: print("Loose threads: %r" % threads)
parser.add_argument('--width', type=int, default=1024, help='width of blitzloop window (ignored in fs)') parser.add_argument('--height', type=int, default=768, help='height of blitzloop window (ignored in fs)') parser.add_argument('--no-audioengine', action="store_true", help='Disable JACK-based audio engine (mic echo effect)') parser.add_argument('--mics', type=csv_list, default=["system:capture_1"], help='Mic input connections (list of JACK ports)') opts = util.get_opts() songs_dir = os.path.expanduser(opts.songdir) print("Loading song DB...") song_database = songlist.SongDatabase(songs_dir) print("Done.") display = graphics.Display(opts.width, opts.height, opts.fullscreen) renderer = graphics.get_renderer().KaraokeRenderer(display) mpv = mpvplayer.Player(display) if not opts.no_audioengine and opts.mics: print(repr(opts.mics)) audio = AudioEngine([s.encode("ascii") for s in opts.mics]) print("Engine sample rate: %dHz" % audio.sample_rate)
def entry(): parser = util.get_argparser() parser.add_argument('songpath', metavar='SONGPATH', help='path to the song file') parser.add_argument('--show-timings', dest='st', action='store_true', help='show mpv timings') parser.add_argument('--offset', type=float, default=0.0, help='song offset') parser.add_argument('--variant', type=int, default=0, help='song variant') opts = util.get_opts() fullscreen = opts.fullscreen s = song.Song(opts.songpath) headstart = 0.3 if fullscreen: display = graphics.Display(1920, 1200, fullscreen, None) else: display = graphics.Display(1280, 720, fullscreen, None) print(display.width, display.height) mpv = mpvplayer.Player(display) mpv.load_song(s) display.set_aspect(mpv.aspect) renderer = graphics.get_renderer().KaraokeRenderer(display) song_layout = layout.SongLayout(s, list(s.variants.keys())[opts.variant], renderer) song_time = -10 speed_i = 0 pitch_i = 0 channels_i = s.channel_defaults for idx, val in enumerate(channels_i): mpv.set_channel(idx, val / 10.0) if opts.offset: mpv.seek_to(opts.offset) def render(): t = time.time() nonlocal song_time while not mpv.eof_reached(): graphics.get_renderer().clear(0, 0, 0, 1) t1 = time.time() mpv.draw() dt = time.time() - t1 mpv.poll() song_time = mpv.get_song_time() or song_time mpv.draw_fade(song_time) renderer.draw(song_time + headstart * 2**(speed_i / 12.0), song_layout) yield None t2 = time.time() if opts.st: print("T:%7.3f/%7.3f B:%7.3f FPS:%.2f draw:%.3f" % (song_time, mpv.duration, s.timing.time2beat(song_time), (1.0 / (t2 - t)), dt)) t = t2 mpv.flip() mpv.shutdown() os._exit(0) pause = False CH_UP = "+456" CH_DOWN = "-123" def key(k): nonlocal speed_i, pitch_i, pause if k == 'KEY_ESCAPE': mpv.shutdown() os._exit(0) elif k == 'f': display.toggle_fullscreen() elif k == '[' and speed_i > -12: speed_i -= 1 print("Speed: %d" % speed_i) mpv.set_speed(2**(-speed_i / 12.0)) elif k == ']' and speed_i < 12: speed_i += 1 print("Speed: %d" % speed_i) mpv.set_speed(2**(-speed_i / 12.0)) elif k == 'KEY_UP' and pitch_i < 12: pitch_i += 1 print("Pitch: %d" % pitch_i) mpv.set_pitch(2**(pitch_i / 12.0)) elif k == 'KEY_DOWN' and pitch_i > -12: pitch_i -= 1 print("Pitch: %d" % pitch_i) mpv.set_pitch(2**(pitch_i / 12.0)) elif k in CH_UP: idx = CH_UP.index(k) if len(channels_i) > idx and channels_i[idx] < 30: channels_i[idx] += 1 print("Channel %d: %d" % (idx, channels_i[idx])) mpv.set_channel(idx, channels_i[idx] / 10.0) elif k in CH_DOWN: idx = CH_DOWN.index(k) if len(channels_i) > idx and channels_i[idx] > 0: channels_i[idx] -= 1 print("Channel %d: %d" % (idx, channels_i[idx])) mpv.set_channel(idx, channels_i[idx] / 10.0) elif k == 'KEY_LEFT': mpv.seek(-10) elif k == 'KEY_RIGHT': mpv.seek(10) elif k == ' ': pause = not pause t = time.time() mpv.set_pause(pause) print("P %.03f" % (time.time() - t)) mpv.play() display.set_render_gen(render) display.set_keyboard_handler(key) display.main_loop() mpv.shutdown()
def entry(): parser = util.get_argparser() parser.add_argument( 'songpath', metavar='SONGPATH', help='path to the song file') parser.add_argument( '--show-timings', dest='st', action='store_true', help='show mpv timings') parser.add_argument( '--offset', type=float, default=0.0, help='song offset') parser.add_argument( '--variant', type=int, default=0, help='song variant') opts = util.get_opts() fullscreen = opts.fullscreen s = song.Song(opts.songpath) headstart = 0.3 if fullscreen: display = graphics.Display(1920, 1200, fullscreen, None) else: display = graphics.Display(1280, 720, fullscreen, None) print(display.width, display.height) mpv = mpvplayer.Player(display) mpv.load_song(s) display.set_aspect(mpv.aspect) renderer = graphics.get_renderer().KaraokeRenderer(display) song_layout = layout.SongLayout(s, list(s.variants.keys())[opts.variant], renderer) song_time = -10 speed_i = 0 pitch_i = 0 channels_i = s.channel_defaults for idx, val in enumerate(channels_i): mpv.set_channel(idx, val / 10.0) if opts.offset: mpv.seek_to(opts.offset) def render(): t = time.time() nonlocal song_time while not mpv.eof_reached(): graphics.get_renderer().clear(0, 0, 0, 1) t1 = time.time() mpv.draw() dt = time.time() - t1 mpv.poll() song_time = mpv.get_song_time() or song_time mpv.draw_fade(song_time) renderer.draw(song_time + headstart * 2**(speed_i/12.0), song_layout) yield None t2 = time.time() if opts.st: print("T:%7.3f/%7.3f B:%7.3f FPS:%.2f draw:%.3f" % (song_time, mpv.duration, s.timing.time2beat(song_time), (1.0/(t2-t)), dt)) t = t2 mpv.flip() mpv.shutdown() os._exit(0) pause = False CH_UP = "+456" CH_DOWN = "-123" def key(k): nonlocal speed_i, pitch_i, pause if k == 'KEY_ESCAPE': mpv.shutdown() os._exit(0) elif k == 'f': display.toggle_fullscreen() elif k == '[' and speed_i > -12: speed_i -= 1 print("Speed: %d" % speed_i) mpv.set_speed(2**(-speed_i/12.0)) elif k == ']' and speed_i < 12: speed_i += 1 print("Speed: %d" % speed_i) mpv.set_speed(2**(-speed_i/12.0)) elif k == 'KEY_UP' and pitch_i < 12: pitch_i += 1 print("Pitch: %d" % pitch_i) mpv.set_pitch(2**(pitch_i/12.0)) elif k == 'KEY_DOWN' and pitch_i > -12: pitch_i -= 1 print("Pitch: %d" % pitch_i) mpv.set_pitch(2**(pitch_i/12.0)) elif k in CH_UP: idx = CH_UP.index(k) if len(channels_i) > idx and channels_i[idx] < 30: channels_i[idx] += 1 print("Channel %d: %d" % (idx, channels_i[idx])) mpv.set_channel(idx, channels_i[idx]/10.0) elif k in CH_DOWN: idx = CH_DOWN.index(k) if len(channels_i) > idx and channels_i[idx] > 0: channels_i[idx] -= 1 print("Channel %d: %d" % (idx, channels_i[idx])) mpv.set_channel(idx, channels_i[idx]/10.0) elif k == 'KEY_LEFT': mpv.seek(-10) elif k == 'KEY_RIGHT': mpv.seek(10) elif k == ' ': pause = not pause t = time.time() mpv.set_pause(pause) print("P %.03f" % (time.time()-t)) mpv.play() display.set_render_gen(render) display.set_keyboard_handler(key) display.main_loop() mpv.shutdown()
import sys from blitzloop import graphics, layout, mpvplayer, song, util parser = util.get_argparser() parser.add_argument( 'songpath', metavar='SONGPATH', help='path to the song file') parser.add_argument( 'quant', metavar='QUANT', type=int, help='quantization of the song') parser.add_argument( '--speed', default=1.0, type=float, help='divisor of the audio speed') parser.add_argument( '--position', default=0.0, type=float, help='starting position in the song, in seconds') opts = util.get_opts() s = song.Song(opts.songpath, ignore_steps=True) display = graphics.Display(1280,720) renderer = graphics.get_renderer().KaraokeRenderer(display) layout = layout.SongLayout(s, list(s.variants.keys())[-1], renderer) step = 0 cur_beat = 0 compound = None compounds = iter(s.compounds) mpv = mpvplayer.Player(None) mpv.load_song(s)
def entry(): data_home = os.getenv('XDG_DATA_HOME', '~/.local/share') songs_dir = os.path.join(data_home, 'blitzloop', 'songs') def csv_list(s): return s.split(",") parser = util.get_argparser() parser.add_argument('--songdir', default=os.path.expanduser(songs_dir), help='directory with songs') parser.add_argument('--host', default='0.0.0.0', help='IP to listen on') parser.add_argument('--port', default=10111, type=int, help='port for the UI') parser.add_argument('--width', type=int, default=1024, help='width of blitzloop window (ignored in fs)') parser.add_argument('--height', type=int, default=768, help='height of blitzloop window (ignored in fs)') parser.add_argument( '--no-audioengine', action="store_true", help='Disable JACK-based audio engine (mic echo effect)') parser.add_argument('--mics', type=csv_list, default=["system:capture_1"], help='Mic input connections (list of JACK ports)') opts = util.get_opts() songs_dir = os.path.expanduser(opts.songdir) print("Loading song DB...") song_database = songlist.SongDatabase(songs_dir) print("Done.") display = graphics.Display(opts.width, opts.height, opts.fullscreen) renderer = graphics.get_renderer().KaraokeRenderer(display) mpv = mpvplayer.Player(display) if not opts.no_audioengine and opts.mics: from blitzloop._audio import AudioEngine print(repr(opts.mics)) audio = AudioEngine([s.encode("ascii") for s in opts.mics]) print("Engine sample rate: %dHz" % audio.sample_rate) queue = songlist.SongQueue() class AudioConfig(object): def __init__(self): self.nmics = len(opts.mics) if not opts.no_audioengine else 0 self.volume = 80 if opts.no_audioengine: self.mic_channels = [] else: self.mic_channels = [{"volume": 80} for i in range(self.nmics)] self.mic_feedback = 20 self.mic_delay = 12 self.headstart = 30 def update(self, song=None): mpv.set_volume(((self.volume / 100.0)**2) * 0.5) if not opts.no_audioengine: for i, j in enumerate(self.mic_channels): audio.set_mic_volume(i, ((j["volume"] / 100.0)**2) * 2.0) audio.set_mic_feedback(self.mic_feedback / 100.0) audio.set_mic_delay(self.mic_delay / 100.0) audio_config = AudioConfig() web.database = song_database web.queue = queue web.audio_config = audio_config server = web.ServerThread(host=opts.host, port=opts.port) server.start() idle_screen = idlescreen.IdleScreen(display) def main_render(): # Wait for element in queue print("Waiting for song to appear in queue...") qe = None with queue.lock: if len(queue) != 0: qe = queue[0] if not qe: idle_screen.reset() graphics.get_renderer().clear(0, 0, 0, 1) for f in idle_screen: audio_config.update() yield None graphics.get_renderer().clear(0, 0, 0, 1) if not qe: with queue.lock: if len(queue) != 0: qe = queue[0] idle_screen.close() for i in range(2): yield None graphics.get_renderer().clear(0, 0, 0, 1) print("Loading audio/video...") mpv.load_song(qe.song) display.set_aspect(mpv.aspect) def update_params(defer=False): mpv.set_speed(1.0 / (2**(qe.speed / 12.0))) mpv.set_pitch(2**(qe.pitch / 12.0)) for i, j in enumerate(qe.channels): mpv.set_channel(i, j["volume"] / 10., defer=defer) mpv.set_pause(qe.pause) update_params(True) mpv.update_mixer(force=True) print("Laying out song...") renderer.reset() variant_key = list(qe.song.variants.keys())[qe.variant] song_layout = layout.SongLayout(qe.song, variant_key, renderer) print("Loaded.") song_time = -10 stopping = False while not (mpv.eof_reached() or (stopping and qe.pause)): while qe.commands: cmd, arg = qe.commands.pop(0) if cmd == "seek": mpv.seek(arg) elif cmd == "seekto": mpv.seek_to(arg) mpv.draw() mpv.poll() song_time = mpv.get_song_time() or song_time if qe.stop and not stopping: stopping = True mpv.fade_out = 2 mpv.duration = min(mpv.duration, song_time + 2) if not stopping: mpv.draw_fade(song_time) speed = 2**(qe.speed / 12.0) renderer.draw(song_time + audio_config.headstart / 100.0 * speed, song_layout) if stopping: fade = mpv.draw_fade(song_time) mpv.set_fadevol(max(fade * 1.3 - 0.3, 0)) update_params() audio_config.update(qe.song) yield None mpv.flip() graphics.get_renderer().clear(0, 0, 0, 1) for i in range(2): yield None graphics.get_renderer().clear(0, 0, 0, 1) print("Song complete.") del song_layout try: queue.pop(qe.qid) except (IndexError, KeyError): pass mpv.stop() display.set_aspect(None) def main(): while True: for i in main_render(): yield i def exit(): print("Exit handler called") mpv.shutdown() if not opts.no_audioengine: audio.shutdown() server.stop() print("Exit handler done") def key(k): if k == 'KEY_ESCAPE': display.queue_exit() elif k == 'f': display.toggle_fullscreen() display.set_render_gen(main) display.set_keyboard_handler(key) display.set_exit_handler(exit) display.main_loop() threads = threading.enumerate() if len(threads) > 1: print("Loose threads: %r" % threads)
# # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA import numpy as np import PIL from OpenGL import arrays from OpenGL.arrays import vbo from blitzloop import texture_font from blitzloop.util import map_from, map_to, get_opts from blitzloop.matrix import Matrix if get_opts().display in ("glut",): import OpenGL.GL as gl import OpenGL.GL.shaders as shaders import OpenGL.GLU as glu else: import OpenGL.GLES2 as gl import OpenGL.GLES2.shaders as shaders glu = None vs_karaoke = """ attribute vec4 coords; attribute vec3 border_color; attribute vec3 fill_color; attribute vec3 outline_color;