Skip to content

Commit

Permalink
Rewriting the clock mechanism entirely
Browse files Browse the repository at this point in the history
  • Loading branch information
Bubobubobubobubo committed Jul 20, 2024
1 parent 13afb5c commit 1fbda24
Show file tree
Hide file tree
Showing 12 changed files with 554 additions and 411 deletions.
42 changes: 9 additions & 33 deletions src/shrimp/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from .configuration import read_configuration, open_config_folder
from .utils import info_message, greeter, alias_param
from .time.clock import Clock, TimePos
from .time.Clock import Clock, TimePos
from functools import partial
from .io.midi import MIDIOut, MIDIIn, list_midi_ports
from .io.osc import OSC
Expand All @@ -11,8 +11,11 @@
from .systems.PlayerSystem.PatternPlayer import Player
from .systems.PlayerSystem.GlobalConfig import global_config as G
import functools
import logging
import os

logging.warning("=========== Program start ==============")

# Do not import signalflow if on Linux or Windows!
current_os = os.uname().sysname
if current_os == "Darwin":
Expand Down Expand Up @@ -40,6 +43,7 @@
for midi_out_port_name, port in all_output_midi_ports.items():
if midi_out_port_name != "instruments" and port:
if CONFIGURATION["editor"]["greeter"]:
logging.info(f"MIDI Output {midi_out_port_name} added for port: {port}")
print(
f"[bold yellow]> MIDI Output [red]{midi_out_port_name}[/red] added for port: [red]{port}[/red] [/bold yellow]"
)
Expand All @@ -56,6 +60,7 @@
)
globals()[name] = new_instrument
if CONFIGURATION["editor"]["greeter"]:
logging.info(f"MIDI Instrument added: {name}")
print(f"[bold yellow]> MIDI Instrument added: [red]{name}[/red] [/bold yellow]")

# Declaring new MIDI controllers
Expand All @@ -67,13 +72,15 @@
)
globals()[name] = new_controller
if CONFIGURATION["editor"]["greeter"]:
logging.info(f"MIDI Controller added: {name}")
print(f"[bold yellow]> MIDI Controller added: [red]{name}[/red] [/bold yellow]")


# Opening MIDI input ports based on user configuration
for midi_in_port_name, port in CONFIGURATION["midi"]["in_ports"].items():
if port is not False:
if CONFIGURATION["editor"]["greeter"]:
logging.info(f"MIDI Input {midi_in_port_name} added for port: {port}")
print(
f"[bold yellow]> MIDI Output [red]{midi_in_port_name}[/red] added for port: [red]{port}[/red] [/bold yellow]"
)
Expand All @@ -83,54 +90,23 @@
# Opening OSC connexions based on user configuration
for osc_port_name, port in CONFIGURATION["osc"]["ports"].items():
if CONFIGURATION["editor"]["greeter"]:
logging.info(f"OSC Port added: {osc_port_name}")
print(f"[bold yellow]> OSC Port added: [red]{osc_port_name}[/red] [/bold yellow]")
globals()[osc_port_name] = OSC(
name=osc_port_name, host=port["host"], port=port["port"], clock=clock
)
env.subscribe(globals()[osc_port_name])

c = clock
now = lambda: clock.beat
next_bar = lambda: clock.next_bar
loop = clock.add
loopr = partial(loop, relative=True)
stop = clock.remove


def loop_now(quant="bar"):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
return func(*args, **kwargs)

if quant == "bar":
info_message(f"Starting [red]{func.__name__}[/red] on next bar")
clock.add(func, clock.next_bar)
elif quant == "beat":
info_message(f"Starting [red]{func.__name__}[/red] on next beat")
clock.add(func, clock.next_beat)
elif quant == "now":
info_message(f"Starting [red]{func.__name__}[/red] now")
clock.add(func, clock.beat)
elif isinstance(quant, (int, float)):
info_message(f"Starting [red]{func.__name__}[/red] in {quant} beats")
clock.add(func, clock.beat + quant)
else:
raise ValueError(
"Invalid quantization option. Choose 'bar', 'beat', 'now', or a numeric value."
)
return wrapper

return decorator


def exit():
"""Exit the interactive shell"""
clock._stop()


clock._start()
clock.add(func=lambda: clock.play(), time=clock.next_bar - clock.now, passthrough=True, once=True)

# == TEST AREA FOR THE PATTERN SYSTEM ======================================================

Expand Down
6 changes: 6 additions & 0 deletions src/shrimp/__main__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
from shrimp import *
from ptpython.repl import embed
from shrimp.configuration import read_configuration, get_ptpython_history_file
import logging

# This is annoying but this line is necessary to stop parso from spamming the logs
logging.getLogger("parso").setLevel(logging.WARNING)

CONFIGURATION = read_configuration()

Expand All @@ -14,6 +18,7 @@ def exit():
if __name__ == "__main__":
match CONFIGURATION["editor"]["default_shell"]:
case "ptpython":
logging.info("Entering ptpython shell.")
from ptpython.repl import embed

embed(
Expand All @@ -25,6 +30,7 @@ def exit():
vi_mode=CONFIGURATION["editor"]["vim_mode"],
)
case "python":
logging.info("Entering Python shell.")
import code

code.interact(local=locals(), banner="", exitmsg="")
Expand Down
9 changes: 8 additions & 1 deletion src/shrimp/configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@
APPAUTHOR = "Raphaël Forment"
USER_DIRECTORY = appdirs.user_data_dir(APPNAME, APPAUTHOR)

logging.basicConfig(
level=logging.DEBUG,
format="%(asctime)s [%(levelname)s] %(message)s",
datefmt="%H:%M:%S",
filename=os.path.join(USER_DIRECTORY, "shrimp.log"),
filemode="w",
)


def _find_default_output_midi_port() -> str:
"""Find the default MIDI port to use by default when config is created."""
Expand Down Expand Up @@ -142,7 +150,6 @@ def read_configuration() -> dict:
try:
with open(config_path, "r") as f:
content = f.read()
logging.debug(f"Configuration file content: {content}")
return json.loads(content)
except json.JSONDecodeError as e:
logging.error(f"Error decoding JSON from the configuration file: {e}")
Expand Down
2 changes: 1 addition & 1 deletion src/shrimp/environment.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from typing import Optional, TYPE_CHECKING

if TYPE_CHECKING:
from .time.clock import Clock
from .time.Clock import Clock


class Environment:
Expand Down
6 changes: 4 additions & 2 deletions src/shrimp/io/midi.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import mido
from ..time.clock import Clock
from ..time.Clock import Clock
from ..environment import Subscriber
import threading
from time import sleep
Expand Down Expand Up @@ -209,11 +209,13 @@ def note(
note=int(note), velocity=int(velocity), channel=int(channel) - 1
),
time=time,
name=f"note_on_{note}{channel}{self.port}",
once=True,
)
self.clock.add(
func=lambda: self._note_off(note=int(note), velocity=0, channel=int(channel) - 1),
time=(time + length) - 0.020,
name=f"note_off_{note}{channel}{self.port}",
time=(time + length) - 0.010,
once=True,
)

Expand Down
2 changes: 1 addition & 1 deletion src/shrimp/io/osc.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from osc4py3.as_eventloop import *
from osc4py3.oscmethod import *
from ..environment import Subscriber
from ..time.clock import Clock
from ..time.Clock import Clock
from ..utils import flatten, kwargs_to_flat_list
from typing import Optional, Any, Callable
from ..systems.PlayerSystem.Rest import Rest
Expand Down
Loading

0 comments on commit 1fbda24

Please sign in to comment.