Finished K-Fêt config

This commit is contained in:
soyouzpanda 2023-12-20 18:27:24 +01:00
commit 6bcd0af329
Signed by: ecoppens
GPG key ID: 54882F92BB178D6A
36 changed files with 1334 additions and 0 deletions

9
eos_midi/__init__.py Normal file
View file

@ -0,0 +1,9 @@
"""Top-level module"""
__author__ = """soyouzpanda"""
__email__ = 'soyouzpanda@soyouzpanda.fr'
__version__ = '0.1.0'
from .eos_object import *
from .eos import *
from .pad import *

202
eos_midi/__main__.py Normal file
View file

@ -0,0 +1,202 @@
"""Main module."""
from .eos import EOSConnection
from .pad import Pad, EventHandler
from .eos_object import FaderBank, Fader, Macro
from lpminimk3 import LaunchpadMiniMk3, find_launchpads, ButtonEvent, Mode
COLORS = [3, 21, 37, 45, 81, 95, 5, 9]
FOCUS_MACROS = [901, 902, 903, 906]
SELECT_MACROS = [304, 303, 305, 302, 301]
SELECT_COLORS = [78, 21, 13, 5, 3]
class AbstractColorEventHandler(EventHandler):
"""Abstract color event handler"""
def __init__(self, launchpad: LaunchpadMiniMk3, line: int, column: int):
super().__init__(f'{column}x{line}')
self._launchpad = launchpad
self._line = line
self._column = column
self._launchpad.panel.led(
self.button_name).color = COLORS[self._column]
def flash(self):
"""Flash only the current button on the line"""
for color in range(8):
self._launchpad.panel.led(
f'{color}x{self._line}').color = COLORS[color]
self._launchpad.panel.led(self.button_name).reset()
self._launchpad.panel.led(self.button_name,
mode='flash').color = COLORS[self._column]
class ColorBumpEventHandler(AbstractColorEventHandler):
"""Bump button Event handler"""
def __init__(self, fader_bank: FaderBank,
launchpad: LaunchpadMiniMk3, color_id: int):
super().__init__(launchpad, 5, color_id)
self._fader = fader_bank.fader(14, color_id + 1)
def on_press(self, _: ButtonEvent):
self._fader.fire(1.0)
def on_release(self, _: ButtonEvent):
self._fader.fire(0.0)
class ColorFxEventHandler(AbstractColorEventHandler):
"""FX button Event handler"""
def __init__(self, fader_bank: FaderBank,
launchpad: LaunchpadMiniMk3, color_id: int):
super().__init__(launchpad, 6, color_id)
self._fader = fader_bank.fader(17, color_id + 1)
def on_press(self, _: ButtonEvent):
self.flash()
self._fader.fire()
class ColorEventHandler(AbstractColorEventHandler):
"""Non-FX button Event handler"""
def __init__(self, fader_bank: FaderBank,
launchpad: LaunchpadMiniMk3, color_id: int):
super().__init__(launchpad, 7, color_id)
self._fader = fader_bank.fader(18, color_id + 1)
def on_press(self, _: ButtonEvent):
self.flash()
self._fader.fire()
class FocusEventHandler(EventHandler):
"""Focus event handler"""
def __init__(self, eos: EOSConnection,
launchpad: LaunchpadMiniMk3, column: int):
super().__init__(f'{column}x2')
self._macro = eos.macro(FOCUS_MACROS[column])
self._launchpad = launchpad
self._launchpad.panel.led(self.button_name).color = 5
def on_press(self, _: ButtonEvent):
for col in range(4):
self._launchpad.panel.led(f'{col}x2').color = 5
self._launchpad.panel.led(self.button_name).reset()
self._launchpad.panel.led(self.button_name,
mode='flash').color = 5
self._macro.fire()
class SimpleFaderEventHandler(EventHandler):
"""Simple fader Event handler"""
def __init__(self, fader: Fader,
launchpad: LaunchpadMiniMk3,
button: str, color: int):
super().__init__(button)
launchpad.panel.led(button).color = color
self._fader = fader
def on_press(self, _: ButtonEvent):
self._fader.fire(1.0)
def on_release(self, _: ButtonEvent):
self._fader.fire(0.0)
class SimpleMacroEventHandler(EventHandler):
"""Simple macro Event handler"""
def __init__(self, macro: Macro,
launchpad: LaunchpadMiniMk3,
button: str, color: int):
super().__init__(button)
launchpad.panel.led(button).color = color
self._macro = macro
def on_press(self, _: ButtonEvent):
self._macro.fire()
class SelectEventHandler(EventHandler):
"""Select Event handler"""
def __init__(self, eos: EOSConnection,
launchpad: LaunchpadMiniMk3,
select_id: int):
super().__init__(f'{select_id + 3}x0')
self._launchpad = launchpad
self._select_id = select_id
self._macro = eos.macro(SELECT_MACROS[self._select_id])
self._launchpad.panel.led(
self.button_name).color = SELECT_COLORS[self._select_id]
def on_press(self, _: ButtonEvent):
for i in range(3, 8):
self._launchpad.panel.led(
f'{i}x0').color = SELECT_COLORS[i - 3]
self._launchpad.panel.led(
self.button_name).reset()
self._launchpad.panel.led(
self.button_name,
mode='flash').color = SELECT_COLORS[self._select_id]
self._macro.fire()
def main():
"""main function"""
launchpad = find_launchpads()[0]
launchpad.open()
launchpad.mode = Mode.PROG
launchpad.panel.reset()
launchpad.clear_event_queue()
eos = EOSConnection("192.168.50.36", 8000)
faderbank = eos.fader_bank()
pad = Pad(launchpad)
# 6è-7è-8è ligne
for i in range(8):
pad.add_event_handler(ColorBumpEventHandler(faderbank, launchpad, i))
pad.add_event_handler(ColorFxEventHandler(faderbank, launchpad, i))
pad.add_event_handler(ColorEventHandler(faderbank, launchpad, i))
# 3è ligne
for i in range(4):
pad.add_event_handler(FocusEventHandler(eos, launchpad, i))
pad.add_event_handler(SimpleFaderEventHandler(
faderbank.fader(6, 7), launchpad, '4x2', 9))
pad.add_event_handler(SimpleFaderEventHandler(
faderbank.fader(5, 2), launchpad, '6x2', 4))
pad.add_event_handler(SimpleFaderEventHandler(
faderbank.fader(5, 4), launchpad, '7x2', 4))
# 2è ligne
pad.add_event_handler(SimpleFaderEventHandler(
faderbank.fader(5, 5), launchpad, '0x1', 21))
pad.add_event_handler(SimpleFaderEventHandler(
faderbank.fader(5, 6), launchpad, '1x1', 88))
pad.add_event_handler(SimpleFaderEventHandler(
faderbank.fader(7, 1), launchpad, '2x1', 78))
pad.add_event_handler(SimpleFaderEventHandler(
faderbank.fader(7, 2), launchpad, '3x1', 32))
pad.add_event_handler(SimpleMacroEventHandler(
eos.macro(401), launchpad, '5x1', 95))
pad.add_event_handler(SimpleMacroEventHandler(
eos.macro(402), launchpad, '6x1', 95))
pad.add_event_handler(SimpleMacroEventHandler(
eos.macro(403), launchpad, '7x1', 95))
# 1ère ligne
pad.add_event_handler(SimpleMacroEventHandler(
eos.macro(6), launchpad, '0x0', 3))
for i in range(5):
pad.add_event_handler(SelectEventHandler(
eos, launchpad, i))
pad.serve_forever()
if __name__ == '__main__':
main()

23
eos_midi/eos.py Normal file
View file

@ -0,0 +1,23 @@
"""EOS"""
from pythonosc.udp_client import SimpleUDPClient
from .eos_object.fader import FaderBank
from .eos_object.channel import Channel
from .eos_object.macro import Macro
class EOSConnection:
"""EOS Connection"""
def __init__(self, address: str, port: int):
self.osc_client = SimpleUDPClient(address, port)
def fader_bank(self):
"""Returns the FaderBank"""
return FaderBank(self.osc_client)
def channel(self, channel_id: int):
"""Returns the Channel {channel_id}"""
return Channel(channel_id, self.osc_client)
def macro(self, macro_id: int):
"""Returns the Macro {macro_id}"""
return Macro(macro_id, self.osc_client)

View file

@ -0,0 +1,3 @@
from .channel import *
from .fader import *
from .macro import *

View file

@ -0,0 +1,29 @@
"""EOS Channel"""
from pythonosc.udp_client import SimpleUDPClient
class Channel:
"""EOS Channel"""
def __init__(self, channel_id: int, osc_client: SimpleUDPClient):
self.channel_id = channel_id
self.osc_client = osc_client
def full(self):
"""Sets channel intensity to full"""
self.osc_client.send_message(f"/eos/chan/{self.channel_id}/full", [])
def min(self):
"""Sets channel intensity to min"""
self.osc_client.send_message(f"/eos/chan/{self.channel_id}/min", [])
def max(self):
"""Sets channel intensity to max"""
self.osc_client.send_message(f"/eos/chan/{self.channel_id}/max", [])
def plus_10(self):
"""Increases channel intensity by 10%"""
self.osc_client.send_message(f"/eos/chan/{self.channel_id}/+%", [])
def minus_10(self):
"""Decreases channel intensity by 10%"""
self.osc_client.send_message(f"/eos/chan/{self.channel_id}/-%", [])

View file

@ -0,0 +1,87 @@
"""EOS Fader"""
from typing import Optional
from pythonosc.udp_client import SimpleUDPClient
class FaderBank:
"""EOS Fader bank"""
def __init__(self, osc_client: SimpleUDPClient):
self.osc_client = osc_client
for i in range(1, 101):
self.osc_client.send_message(
f"/eos/fader/{i}/config/{i}/10", [])
def page(self, page: int):
"""Returns the page {page}"""
return FaderPage(page, self.osc_client)
def fader(self, page: int, fader: int):
"""Returns the fader {fader} of page {page}"""
return FaderPage(page, self.osc_client).fader(fader)
class FaderPage:
"""EOS Fader page"""
def __init__(self, page: int, osc_client: SimpleUDPClient):
self.page = page
self.osc_client = osc_client
def fader(self, fader: int):
"""Returns the fader {fader} of the page"""
return Fader(self.page, fader, self.osc_client)
def next(self):
"""Returns the next page"""
return FaderPage(min(100, self.page + 1), self.osc_client)
def previous(self):
"""Returns the previous page"""
return FaderPage(max(1, self.page - 1), self.osc_client)
class Fader:
"""EOS Fader"""
def __init__(self, page: int, fader: int,
osc_client: SimpleUDPClient):
self.page = page
self.fader = fader
self.osc_client = osc_client
def fire(self, value: Optional[float] = None):
"""Starts effect of the fader"""
if value:
self.osc_client.send_message(
f"/eos/fader/{self.page}/{self.fader}/fire", [value])
else:
self.osc_client.send_message(
f"/eos/fader/{self.page}/{self.fader}/fire", [])
def stop(self):
"""Stops effect of the fader"""
self.osc_client.send_message(
f"/eos/fader/{self.page}/{self.fader}/stop", [])
def full(self):
"""Sets the fader to full"""
self.osc_client.send_message(
f"/eos/fader/{self.page}/{self.fader}/full", [])
def min(self):
"""Sets the fader to minimum"""
self.osc_client.send_message(
f"/eos/fader/{self.page}/{self.fader}/min", [])
def max(self):
"""Sets the fader to maximum"""
self.osc_client.send_message(
f"/eos/fader/{self.page}/{self.fader}/max", [])
def plus_10(self):
"""Increases the fader by 10%"""
self.osc_client.send_message(
f"/eos/fader/{self.page}/{self.fader}/+%", [])
def minus_10(self):
"""Decreases the fader by 10%"""
self.osc_client.send_message(
f"/eos/fader/{self.page}/{self.fader}/-%", [])

View file

@ -0,0 +1,13 @@
""""EOS Macro"""
from pythonosc.udp_client import SimpleUDPClient
class Macro:
"""EOS Macro"""
def __init__(self, macro_id: int, osc_client: SimpleUDPClient):
self.macro_id = macro_id
self.osc_client = osc_client
def fire(self):
"""Fires macro"""
self.osc_client.send_message(f"/eos/macro/{self.macro_id}/fire", [])

View file

@ -0,0 +1,3 @@
"""MIDI Controller, Launchpad Mini MK3"""
from lpminimk3 import Mode, find_launchpad

74
eos_midi/pad.py Normal file
View file

@ -0,0 +1,74 @@
"""Launchpad"""
from lpminimk3 import LaunchpadMiniMk3, ButtonEvent
VALID_BUTTONS = [
'up', 'down', 'left', 'right', 'session', 'drums', 'keys', 'user',
'scene_launch_1', 'scene_launch_2', 'scene_launch_3', 'scene_launch_4',
'scene_launch_5', 'scene_launch_6', 'scene_launch_7', 'stop_solo_mute',
]
class EventHandler:
"""Event handler for launchpad"""
def __init__(self, button_name: str):
self._button_name = button_name
@property
def button_name(self):
"""Returns button name"""
return self._button_name
def on_press(self, _: ButtonEvent):
"""On button pressed"""
def on_release(self, _: ButtonEvent):
"""On button released"""
class Pad:
"""Pad Wrapper"""
def __init__(self, launchpad: LaunchpadMiniMk3):
self._launchpad = launchpad
self._event_handlers: dict[str, list[EventHandler]] = {}
def _validate_button(self, button: str | tuple[int, int]) -> str:
if isinstance(button, str):
if button in VALID_BUTTONS:
return button
split = button.split('x')
if len(split) == 2 and \
split[0].isdigit() and split[1].isdigit() and \
int(split[0]) >= 0 and int(split[0]) < 8 and \
int(split[1]) >= 0 and int(split[1]) < 8:
return button
raise ValueError(button)
if isinstance(button, tuple) and len(button) == 2 and \
isinstance(button[0], int) and isinstance(button[1], int) and \
button[0] >= 0 and button[0] < 8 and \
button[1] >= 0 and button[1] < 8:
return str(button[0]) + 'x' + str(button[1])
raise ValueError(button)
def add_event_handler(self, handler: EventHandler):
"""Adds a event handler"""
button = self._validate_button(handler.button_name)
lst = self._event_handlers.get(button)
if lst:
lst.append(handler)
else:
self._event_handlers[button] = [handler]
def serve_forever(self):
"""Servers forever"""
buttons = self._launchpad.panel.buttons()
while True:
event = buttons.poll_for_event()
if isinstance(event, ButtonEvent):
if event.type == ButtonEvent.PRESS:
for handler in self._event_handlers.get(
event.button.name, []):
handler.on_press(event)
elif event.type == ButtonEvent.RELEASE:
for handler in self._event_handlers.get(
event.button.name, []):
handler.on_release(event)