litoid 0.1.0__tar.gz → 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. litoid-0.2.0/PKG-INFO +37 -0
  2. litoid-0.2.0/litoid/.DS_Store +0 -0
  3. {litoid-0.1.0 → litoid-0.2.0}/litoid/__main__.py +2 -1
  4. litoid-0.2.0/litoid/io/.DS_Store +0 -0
  5. {litoid-0.1.0 → litoid-0.2.0}/litoid/io/dmx.py +1 -0
  6. {litoid-0.1.0 → litoid-0.2.0}/litoid/io/hotkey.py +5 -3
  7. {litoid-0.1.0 → litoid-0.2.0}/litoid/io/key_mouse.py +4 -2
  8. litoid-0.2.0/litoid/io/midi/__init__.py +3 -0
  9. {litoid-0.1.0 → litoid-0.2.0}/litoid/io/midi/message.py +20 -28
  10. {litoid-0.1.0 → litoid-0.2.0}/litoid/io/midi/midi.py +9 -5
  11. {litoid-0.1.0 → litoid-0.2.0}/litoid/io/osc.py +5 -3
  12. {litoid-0.1.0 → litoid-0.2.0}/litoid/io/player.py +8 -5
  13. {litoid-0.1.0 → litoid-0.2.0}/litoid/io/recorder.py +7 -3
  14. {litoid-0.1.0 → litoid-0.2.0}/litoid/io/track.py +5 -4
  15. {litoid-0.1.0 → litoid-0.2.0}/litoid/litoid.py +5 -2
  16. {litoid-0.1.0 → litoid-0.2.0}/litoid/log.py +6 -4
  17. litoid-0.2.0/litoid/scenes/.DS_Store +0 -0
  18. {litoid-0.1.0 → litoid-0.2.0}/litoid/scenes/compose.py +2 -1
  19. {litoid-0.1.0 → litoid-0.2.0}/litoid/scenes/rgb_keyboard.py +1 -0
  20. litoid-0.2.0/litoid/state/.DS_Store +0 -0
  21. {litoid-0.1.0 → litoid-0.2.0}/litoid/state/instrument.py +3 -2
  22. {litoid-0.1.0 → litoid-0.2.0}/litoid/state/instruments.py +6 -4
  23. {litoid-0.1.0 → litoid-0.2.0}/litoid/state/lamp.py +6 -4
  24. {litoid-0.1.0 → litoid-0.2.0}/litoid/state/state.py +9 -9
  25. litoid-0.2.0/litoid/ui/.DS_Store +0 -0
  26. {litoid-0.1.0 → litoid-0.2.0}/litoid/ui/action.py +4 -3
  27. {litoid-0.1.0 → litoid-0.2.0}/litoid/ui/controller.py +9 -6
  28. {litoid-0.1.0 → litoid-0.2.0}/litoid/ui/drawing_canvas.py +2 -1
  29. {litoid-0.1.0 → litoid-0.2.0}/litoid/ui/event.py +3 -1
  30. {litoid-0.1.0 → litoid-0.2.0}/litoid/ui/layout.py +9 -7
  31. {litoid-0.1.0 → litoid-0.2.0}/litoid/ui/model.py +2 -1
  32. {litoid-0.1.0 → litoid-0.2.0}/litoid/ui/ui.py +10 -6
  33. {litoid-0.1.0 → litoid-0.2.0}/litoid/ui/view.py +7 -5
  34. litoid-0.2.0/litoid/util/.DS_Store +0 -0
  35. {litoid-0.1.0 → litoid-0.2.0}/litoid/util/file.py +2 -1
  36. {litoid-0.1.0 → litoid-0.2.0}/litoid/util/has_thread.py +4 -3
  37. {litoid-0.1.0 → litoid-0.2.0}/litoid/util/play.py +3 -2
  38. {litoid-0.1.0 → litoid-0.2.0}/litoid/util/smooth.py +2 -1
  39. {litoid-0.1.0 → litoid-0.2.0}/litoid/util/thread_queue.py +3 -1
  40. {litoid-0.1.0 → litoid-0.2.0}/litoid/util/timed_heap.py +5 -2
  41. litoid-0.2.0/pyproject.toml +55 -0
  42. litoid-0.1.0/LICENSE +0 -21
  43. litoid-0.1.0/PKG-INFO +0 -35
  44. litoid-0.1.0/litoid/io/midi/__init__.py +0 -3
  45. litoid-0.1.0/pyproject.toml +0 -38
  46. {litoid-0.1.0 → litoid-0.2.0}/README.md +0 -0
  47. {litoid-0.1.0 → litoid-0.2.0}/litoid/__init__.py +0 -0
  48. {litoid-0.1.0 → litoid-0.2.0}/litoid/app.py +0 -0
  49. {litoid-0.1.0 → litoid-0.2.0}/litoid/io/__init__.py +0 -0
  50. {litoid-0.1.0 → litoid-0.2.0}/litoid/scenes/__init__.py +0 -0
  51. {litoid-0.1.0 → litoid-0.2.0}/litoid/state/__init__.py +0 -0
  52. {litoid-0.1.0 → litoid-0.2.0}/litoid/state/level.py +0 -0
  53. {litoid-0.1.0 → litoid-0.2.0}/litoid/state/scene.py +0 -0
  54. {litoid-0.1.0 → litoid-0.2.0}/litoid/ui/__init__.py +0 -0
  55. {litoid-0.1.0 → litoid-0.2.0}/litoid/ui/canvas_window.py +1 -1
  56. {litoid-0.1.0 → litoid-0.2.0}/litoid/ui/defaults.py +0 -0
  57. {litoid-0.1.0 → litoid-0.2.0}/litoid/util/__init__.py +0 -0
  58. {litoid-0.1.0 → litoid-0.2.0}/litoid/util/is_running.py +0 -0
litoid-0.2.0/PKG-INFO ADDED
@@ -0,0 +1,37 @@
1
+ Metadata-Version: 2.4
2
+ Name: litoid
3
+ Version: 0.2.0
4
+ Summary: 💡Sequence DMX lighting 💡
5
+ Author: Tom Ritchford
6
+ Author-email: Tom Ritchford <tom@swirly.com>
7
+ License-Expression: MIT
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Programming Language :: Python :: 3.11
10
+ Classifier: Programming Language :: Python :: 3.12
11
+ Classifier: Programming Language :: Python :: 3.13
12
+ Classifier: Programming Language :: Python :: 3.14
13
+ Requires-Dist: python-osc>=1.8.1
14
+ Requires-Dist: datacls>=4.6.0
15
+ Requires-Dist: mido>=1.2.10
16
+ Requires-Dist: tomlkit>=0.11.6
17
+ Requires-Dist: numpy>=1.24.2
18
+ Requires-Dist: pynput>=1.7.6
19
+ Requires-Dist: python-rtmidi>=1.5.4
20
+ Requires-Dist: xmod>=1.4.0
21
+ Requires-Dist: pyenttec>=1.4
22
+ Requires-Dist: typer>=0.7.0
23
+ Requires-Dist: dtyper>=2.1.0
24
+ Requires-Dist: pysimplegui
25
+ Requires-Dist: psgdemos>=1.12.1
26
+ Requires-Dist: pyperclip>=1.8.2
27
+ Requires-Dist: simpleaudio>=1.0.4
28
+ Requires-Dist: ipython>=8.12.0
29
+ Requires-Dist: clsprop>=1.1.0
30
+ Requires-Dist: matplotlib>=3.7.1
31
+ Requires-Dist: distinctipy>=1.2.2
32
+ Requires-Dist: coverage>=7.3.2,<8
33
+ Requires-Python: >=3.11
34
+ Description-Content-Type: text/markdown
35
+
36
+ # litoid
37
+ Sequence DMX lighting
Binary file
@@ -6,9 +6,10 @@ def cli():
6
6
 
7
7
 
8
8
  def gui():
9
- from .ui.controller import Controller
10
9
  import time
11
10
 
11
+ from .ui.controller import Controller
12
+
12
13
  try:
13
14
  Controller().start()
14
15
  finally:
Binary file
@@ -1,4 +1,5 @@
1
1
  from functools import cached_property
2
+
2
3
  import datacls
3
4
  import pyenttec
4
5
 
@@ -1,8 +1,10 @@
1
- from ..util.has_thread import HasThread
1
+ from collections.abc import Callable
2
2
  from functools import cached_property, partial
3
- from pynput import keyboard
4
- from typing import Callable
3
+
5
4
  import datacls
5
+ from pynput import keyboard
6
+
7
+ from ..util.has_thread import HasThread
6
8
 
7
9
 
8
10
  @datacls.mutable
@@ -1,8 +1,10 @@
1
- from ..util.has_thread import HasThread
2
- from typing import Callable
1
+ from collections.abc import Callable
2
+
3
3
  import datacls
4
4
  import pynput
5
5
 
6
+ from ..util.has_thread import HasThread
7
+
6
8
 
7
9
  @datacls
8
10
  class _Base(HasThread):
@@ -0,0 +1,3 @@
1
+ __all__ = ('MidiInput',)
2
+
3
+ from .midi import MidiInput
@@ -1,7 +1,7 @@
1
1
  import clsprop
2
2
  import xmod
3
3
 
4
- _PITCH = 0xe0
4
+ _PITCH = 0xE0
5
5
  _SYSEX = 0xF0
6
6
 
7
7
 
@@ -18,10 +18,9 @@ class MidiMessage:
18
18
  if data is not None:
19
19
  self.data = data
20
20
  else:
21
- self.data = (
22
- [self.status_start]
23
- + [kwargs.pop(f, 0) or 0 for f in self.fields]
24
- )
21
+ self.data = [self.status_start] + [
22
+ kwargs.pop(f, 0) or 0 for f in self.fields
23
+ ]
25
24
 
26
25
  if bad := [k for k, v in kwargs.items() if v is not None]:
27
26
  assert (data is None) or not kwargs, f'{data=} {kwargs=}'
@@ -40,11 +39,7 @@ class MidiMessage:
40
39
 
41
40
  @clsprop
42
41
  def size(cls) -> int:
43
- return (
44
- len(cls.fields)
45
- + (not cls.has_channel)
46
- + (cls.status_start == _PITCH)
47
- )
42
+ return len(cls.fields) + (not cls.has_channel) + (cls.status_start == _PITCH)
48
43
 
49
44
  @property
50
45
  def status(self):
@@ -106,7 +101,7 @@ def _class(status_start, name, *props):
106
101
  if _has_channel(status_start):
107
102
  parent = MidiChannelMessage
108
103
  if status_start == _PITCH:
109
- fields = 'pitch',
104
+ fields = ('pitch',)
110
105
 
111
106
  fields = 'channel', *props
112
107
  else:
@@ -184,35 +179,32 @@ _CHANNEL = (
184
179
  # Channel messages
185
180
  _class(0x80, 'NoteOff', 'note', 'velocity'),
186
181
  _class(0x90, 'NoteOn', 'note', 'velocity'),
187
- _class(0xa0, 'Polytouch', 'note', 'value'),
188
- _class(0xb0, 'ControlChange', 'control', 'value'),
189
- _class(0xc0, 'ProgramChange', 'program'),
190
- _class(0xd0, 'Aftertouch', 'value'),
182
+ _class(0xA0, 'Polytouch', 'note', 'value'),
183
+ _class(0xB0, 'ControlChange', 'control', 'value'),
184
+ _class(0xC0, 'ProgramChange', 'program'),
185
+ _class(0xD0, 'Aftertouch', 'value'),
191
186
  _class(_PITCH, 'Pitch', 'pitch_lsb', 'pitch_hsb'),
192
187
  )
193
188
 
194
189
  _SYSTEM = (
195
190
  # System common messages.
196
191
  _class(_SYSEX, 'Sysex'),
197
- _class(0xf1, 'QuarterFrame', 'frame_type', 'frame_value'),
198
- _class(0xf2, 'Songpos', 'pos'),
199
- _class(0xf3, 'SongSelect', 'song'),
200
-
192
+ _class(0xF1, 'QuarterFrame', 'frame_type', 'frame_value'),
193
+ _class(0xF2, 'Songpos', 'pos'),
194
+ _class(0xF3, 'SongSelect', 'song'),
201
195
  None, # 0xf4
202
196
  None, # 0xf5
203
- _class(0xf6, 'TuneRequest'),
197
+ _class(0xF6, 'TuneRequest'),
204
198
  None, # 0xf7 is sysex end
205
-
206
199
  # System real time messages.
207
- _class(0xf8, 'Clock'),
200
+ _class(0xF8, 'Clock'),
208
201
  None, # 0xf9
209
- _class(0xfa, 'Start'),
210
- _class(0xfb, 'Continue'),
211
-
212
- _class(0xfc, 'Stop'),
202
+ _class(0xFA, 'Start'),
203
+ _class(0xFB, 'Continue'),
204
+ _class(0xFC, 'Stop'),
213
205
  None, # 0xfd
214
- _class(0xfe, 'ActiveSensing'),
215
- _class(0xff, 'Reset'),
206
+ _class(0xFE, 'ActiveSensing'),
207
+ _class(0xFF, 'Reset'),
216
208
  )
217
209
 
218
210
  MESSAGE_CLASSES = tuple(c for c in _CHANNEL for i in range(16)) + _SYSTEM
@@ -1,11 +1,15 @@
1
- from .message import MidiMessage
1
+ import time
2
+ from collections.abc import Callable
2
3
  from functools import cached_property
3
- from litoid.util.has_thread import HasThread
4
- from rtmidi import midiutil, MidiIn
5
- from typing import Callable
4
+
6
5
  import datacls
7
6
  import mido
8
- import time
7
+ from rtmidi import MidiIn, midiutil
8
+
9
+ from litoid.util.has_thread import HasThread
10
+
11
+ from .message import MidiMessage
12
+
9
13
  SPIN_TIME = 0.003
10
14
 
11
15
 
@@ -1,9 +1,11 @@
1
- from ..util.thread_queue import ThreadQueue
1
+ from collections.abc import Callable
2
2
  from functools import cached_property
3
+
4
+ import datacls
3
5
  from pythonosc.dispatcher import Dispatcher
4
6
  from pythonosc.osc_server import BlockingOSCUDPServer
5
- from typing import Callable
6
- import datacls
7
+
8
+ from ..util.thread_queue import ThreadQueue
7
9
 
8
10
 
9
11
  @datacls.mutable
@@ -1,10 +1,13 @@
1
- from .recorder import Recorder
2
- from .track import Track
1
+ import time
2
+ from collections.abc import Callable
3
3
  from functools import cached_property, total_ordering
4
- from litoid.util.timed_heap import TimedHeap
5
- from typing import Callable
4
+
6
5
  import datacls
7
- import time
6
+
7
+ from litoid.util.timed_heap import TimedHeap
8
+
9
+ from .recorder import Recorder
10
+ from .track import Track
8
11
 
9
12
  INFINITE = float('inf')
10
13
 
@@ -1,9 +1,12 @@
1
- from .track import Track
2
- from litoid import log
1
+ import time as _time
3
2
  from pathlib import Path
3
+
4
4
  import datacls
5
5
  import numpy as np
6
- import time as _time
6
+
7
+ from litoid import log
8
+
9
+ from .track import Track
7
10
 
8
11
  SEP = '-'
9
12
 
@@ -21,6 +24,7 @@ class Recorder:
21
24
  This only works for protocols where you can deduce the length of the packet
22
25
  from the initial bytes only.
23
26
  """
27
+
24
28
  name: str
25
29
  path: Path | None = None
26
30
  tracks: dict = datacls.field(dict[str, Track])
@@ -1,4 +1,5 @@
1
1
  from functools import cached_property
2
+
2
3
  import datacls
3
4
  import numpy as np
4
5
 
@@ -26,7 +27,7 @@ class Track:
26
27
 
27
28
  def get_message(self, i) -> tuple[np.ndarray, float]:
28
29
  b = i * self.byte_width
29
- return self.data[b:b + self.byte_width]
30
+ return self.data[b : b + self.byte_width]
30
31
 
31
32
  def append(self, data: np.ndarray, time: float):
32
33
  assert self.byte_width == len(data)
@@ -42,12 +43,12 @@ class Track:
42
43
  self.count += 1
43
44
 
44
45
  def asdict(self):
45
- return dict(zip(('times', 'data'), self.astuple()))
46
+ return dict(zip(('times', 'data'), self.astuple(), strict=True))
46
47
 
47
48
  def astuple(self):
48
49
  return (
49
- self.times[0:self.count],
50
- self.data[0:self.byte_width * self.count],
50
+ self.times[0 : self.count],
51
+ self.data[0 : self.byte_width * self.count],
51
52
  )
52
53
 
53
54
  @classmethod
@@ -1,12 +1,14 @@
1
1
  # DEPRECATED
2
2
 
3
- from . import app
4
- from .state import state
5
3
  from functools import cached_property
6
4
  from pathlib import Path
5
+
7
6
  import dtyper
8
7
  import xmod
9
8
 
9
+ from . import app
10
+ from .state import state
11
+
10
12
 
11
13
  @xmod
12
14
  @app.command()
@@ -14,6 +16,7 @@ def litoid(
14
16
  state_path: Path = app.Argument(None, help='Path to the state file'),
15
17
  ):
16
18
  import IPython
19
+
17
20
  litoid = Litoid(**locals())
18
21
 
19
22
  scope_vars = {'li': litoid, 'litoid': litoid}
@@ -1,12 +1,14 @@
1
- from .util import play
2
- from pathlib import Path
3
- from functools import wraps
4
- import PySimpleGUI as sg
5
1
  import inspect
6
2
  import os
7
3
  import sys
4
+ from functools import wraps
5
+ from pathlib import Path
6
+
7
+ import PySimpleGUI as sg
8
8
  import xmod
9
9
 
10
+ from .util import play
11
+
10
12
  ROOT = Path(__file__).parent
11
13
  DEBUG = os.environ.get('DEBUG', '').strip().lower().startswith('t')
12
14
  POPUP_ERRORS = False
Binary file
@@ -1,6 +1,7 @@
1
- from ..state import scene, state
2
1
  import datacls
3
2
 
3
+ from ..state import scene, state
4
+
4
5
 
5
6
  @datacls
6
7
  class Compose(scene.Scene):
@@ -1,4 +1,5 @@
1
1
  from pynput.keyboard import Events
2
+
2
3
  from ..state.scene import Scene
3
4
 
4
5
 
Binary file
@@ -1,8 +1,9 @@
1
- from .level import Level
2
1
  from collections import ChainMap
3
2
  from functools import cached_property
3
+
4
4
  import datacls
5
5
 
6
+ from .level import Level
6
7
 
7
8
  Channel = int | str
8
9
 
@@ -13,7 +14,7 @@ class ValueNames(dict):
13
14
  super().__init__((k, v) for v, k in items)
14
15
 
15
16
  self.inv = []
16
- for (v1, k1), (v2, k2) in zip(items, items[1:] + [(256, None)]):
17
+ for (v1, k1), (v2, _) in zip(items, items[1:] + [(256, None)], strict=True):
17
18
  self.inv.extend(k1 for i in range(v1, v2))
18
19
 
19
20
 
@@ -1,10 +1,12 @@
1
- from ..util import file
2
- from .instrument import Instrument
3
1
  from functools import cache
4
2
  from pathlib import Path
3
+
5
4
  import xmod
6
5
 
7
- __all__ = 'instruments',
6
+ from ..util import file
7
+ from .instrument import Instrument
8
+
9
+ __all__ = ('instruments',)
8
10
 
9
11
  ROOT = Path(__file__).parents[2]
10
12
  DATA = ROOT / 'data'
@@ -22,7 +24,7 @@ def instruments():
22
24
  presets = files('presets')
23
25
 
24
26
  assert defs.keys() == presets.keys()
25
- kdp = zip(defs.keys(), defs.values(), presets.values())
27
+ kdp = zip(defs.keys(), defs.values(), presets.values(), strict=True)
26
28
  instruments = {k: Instrument(k, user_presets=p, **d) for k, d, p in kdp}
27
29
  return instruments
28
30
 
@@ -1,8 +1,10 @@
1
- from . import instruments
2
- from ..io.dmx import DMX
3
1
  from functools import cached_property
2
+
4
3
  import datacls
5
4
 
5
+ from ..io.dmx import DMX
6
+ from . import instruments
7
+
6
8
 
7
9
  @datacls.mutable
8
10
  class LampDesc:
@@ -19,7 +21,7 @@ class LampDesc:
19
21
  return len(self.instrument.channels)
20
22
 
21
23
  def make(self, dmx: DMX):
22
- frame = dmx.frame[self.offset:self.offset + self.size]
24
+ frame = dmx.frame[self.offset : self.offset + self.size]
23
25
  return Lamp(frame=frame, dmx=dmx, **self.asdict())
24
26
 
25
27
  @cached_property
@@ -35,7 +37,7 @@ class Lamp(LampDesc):
35
37
  def set_levels(self, d: dict):
36
38
  d = self.instrument.remap_dict(d)
37
39
  it = range(len(self.frame))
38
- self.frame[:] = (bytes(max(0, min(255, d.get(i, 0))) for i in it))
40
+ self.frame[:] = bytes(max(0, min(255, d.get(i, 0))) for i in it)
39
41
  self.send_packet()
40
42
 
41
43
  def set_level(self, i: int | slice, v):
@@ -1,12 +1,14 @@
1
- from . import lamp as _lamp
2
- from ..io import dmx, key_mouse, midi, osc
3
- from ..util import file, is_running, timed_heap
1
+ import time
4
2
  from functools import cached_property, wraps
5
3
  from pathlib import Path
4
+
6
5
  import datacls
7
- import time
8
6
  import xmod
9
7
 
8
+ from ..io import dmx, key_mouse, midi, osc
9
+ from ..util import file, is_running, timed_heap
10
+ from . import lamp as _lamp
11
+
10
12
  SPIN_TIME = 0.05
11
13
  STATE_FILE = Path(__file__).parents[2] / 'state.toml'
12
14
  assert STATE_FILE.exists()
@@ -39,10 +41,7 @@ class State(is_running.IsRunning):
39
41
  @cached_property
40
42
  def midi_input(self):
41
43
  if self.midi_input_name:
42
- return midi.MidiInput(
43
- callback=self.callback,
44
- name=self.midi_input_name
45
- )
44
+ return midi.MidiInput(callback=self.callback, name=self.midi_input_name)
46
45
 
47
46
  @cached_property
48
47
  def mouse(self):
@@ -73,7 +72,8 @@ class State(is_running.IsRunning):
73
72
  self.mouse.start()
74
73
  else:
75
74
  self.keyboard.start()
76
- self.lamps
75
+ self.lamps # noqa: B018
76
+
77
77
  self.midi_input and self.midi_input.start()
78
78
  self.osc_server.start()
79
79
  self.timed_heap.start()
Binary file
@@ -1,6 +1,7 @@
1
- from .. import log
2
- import PySimpleGUI as sg
3
1
  import pyperclip
2
+ import PySimpleGUI as sg
3
+
4
+ from .. import log
4
5
 
5
6
 
6
7
  class Action:
@@ -81,7 +82,7 @@ class Action:
81
82
 
82
83
  def revert(self):
83
84
  ch = sg.popup_ok_cancel(
84
- f'Revert to saved for {self.controller.iname}?', title='Revert'
85
+ f'Revert to saved for {self.controller.iname}?', title='Revert'
85
86
  )
86
87
  if ch == 'OK':
87
88
  self.model.revert()
@@ -1,11 +1,13 @@
1
+ import json
2
+ from pathlib import Path
3
+
4
+ from litoid import log
5
+ from litoid.io.midi.message import ControlChange
6
+ from litoid.state.scene import CallbackScene
7
+
1
8
  from . import action
2
9
  from .model import Model
3
10
  from .view import View
4
- from litoid import log
5
- from litoid.state.scene import CallbackScene
6
- from litoid.io.midi.message import ControlChange
7
- from pathlib import Path
8
- import json
9
11
 
10
12
 
11
13
  class Controller:
@@ -62,7 +64,8 @@ class Controller:
62
64
  self.view.update_presets(self.model.iname, value=preset_name)
63
65
  self.lamp.set_levels(self.model.selected_preset)
64
66
  self.view.update_instrument(
65
- self.instrument, self.model.selected_preset,
67
+ self.instrument,
68
+ self.model.selected_preset,
66
69
  )
67
70
 
68
71
  def blackout(self):
@@ -1,7 +1,8 @@
1
1
  from functools import cached_property
2
+
3
+ import datacls
2
4
  from matplotlib import pyplot as plt
3
5
  from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
4
- import datacls
5
6
 
6
7
 
7
8
  @datacls
@@ -1,6 +1,7 @@
1
1
  from functools import cached_property
2
- import PySimpleGUI as sg
2
+
3
3
  import datacls
4
+ import PySimpleGUI as sg
4
5
 
5
6
 
6
7
  @datacls
@@ -11,6 +12,7 @@ class Event:
11
12
  action[.name[.channel]]
12
13
 
13
14
  """
15
+
14
16
  window: str
15
17
  key: str
16
18
  values: dict | None = None
@@ -1,8 +1,10 @@
1
- from . defaults import COMMANDS
2
1
  from functools import partial
2
+
3
3
  import PySimpleGUI as sg
4
4
  import xmod
5
5
 
6
+ from .defaults import COMMANDS
7
+
6
8
  SLIDER = {
7
9
  'range': (0, 255),
8
10
  'orientation': 'h',
@@ -15,14 +17,14 @@ COMBO = {
15
17
  'readonly': True,
16
18
  }
17
19
  BUTTON = {
18
- 'border_width': 1,
19
- 'expand_x': not True,
20
+ 'border_width': 1,
21
+ 'expand_x': not True,
20
22
  }
21
23
  TEXT = {
22
- 'relief': 'raised',
23
- 'border_width': 1,
24
- 'expand_x': not True,
25
- 'justification': 'center',
24
+ 'relief': 'raised',
25
+ 'border_width': 1,
26
+ 'expand_x': not True,
27
+ 'justification': 'center',
26
28
  }
27
29
  Text = partial(sg.Text, **TEXT)
28
30
  SLIDER_SIZE = 32, 30
@@ -1,8 +1,9 @@
1
+ import copy
2
+
1
3
  from litoid import log
2
4
  from litoid.io.midi.message import ControlChange, MidiMessage
3
5
  from litoid.io.recorder import Recorder
4
6
  from litoid.state import instruments
5
- import copy
6
7
 
7
8
 
8
9
  class Model:
@@ -1,10 +1,13 @@
1
- from ..util.is_running import IsRunning
2
- from .event import Event
3
1
  from functools import cached_property
4
- from litoid import log
5
2
  from pathlib import Path
6
- import PySimpleGUI as sg
3
+
7
4
  import datacls
5
+ import PySimpleGUI as sg
6
+
7
+ from litoid import log
8
+
9
+ from ..util.is_running import IsRunning
10
+ from .event import Event
8
11
 
9
12
  SUFFIX = '.ico'
10
13
  ICON_PATH = Path(__file__).parents[2] / 'images/tom-swirly.ico'
@@ -55,9 +58,10 @@ class UI(UIDesc, IsRunning):
55
58
  title,
56
59
  [
57
60
  *([sg.T(m)] for m in messages),
58
- [sg.Yes(s=10), sg.No(s=10), sg.Cancel(s=15)]
61
+ [sg.Yes(s=10), sg.No(s=10), sg.Cancel(s=15)],
59
62
  ],
60
- disable_close=True)
63
+ disable_close=True,
64
+ )
61
65
  choice, _ = popup.read(close=True)
62
66
  return choice
63
67
 
@@ -1,11 +1,13 @@
1
- from . import defaults, layout, ui
2
- from .drawing_canvas import DrawingCanvas
3
- from ..state.level import Level
4
- from ..state.state import State, make_state
1
+ from collections.abc import Callable
5
2
  from functools import cached_property
6
- from typing import Callable
3
+
7
4
  import datacls
8
5
 
6
+ from ..state.level import Level
7
+ from ..state.state import State, make_state
8
+ from . import defaults, layout, ui
9
+ from .drawing_canvas import DrawingCanvas
10
+
9
11
 
10
12
  @datacls.mutable
11
13
  class View(ui.UI):
Binary file
@@ -1,7 +1,8 @@
1
1
  import json
2
- import tomlkit
3
2
  import tomllib
4
3
 
4
+ import tomlkit
5
+
5
6
 
6
7
  def load(path):
7
8
  t = path.read_text()
@@ -1,8 +1,9 @@
1
- from .is_running import IsRunning
1
+ import sys
2
+ import traceback
2
3
  from functools import cached_property
3
4
  from threading import Thread
4
- import traceback
5
- import sys
5
+
6
+ from .is_running import IsRunning
6
7
 
7
8
 
8
9
  class HasThread(IsRunning):
@@ -1,7 +1,8 @@
1
- from threading import Thread, Lock
2
1
  from pathlib import Path
3
- import xmod
2
+ from threading import Lock, Thread
3
+
4
4
  import simpleaudio as sa
5
+ import xmod
5
6
 
6
7
  DEFAULT = Path(__file__).parents[2] / 'audio/Click Mini 3.wav'
7
8
  _RUNNING = False
@@ -1,6 +1,7 @@
1
- import xmod
2
1
  import pprint
3
2
 
3
+ import xmod
4
+
4
5
 
5
6
  @xmod
6
7
  def smooth(it):
@@ -1,13 +1,15 @@
1
- from .has_thread import HasThread
2
1
  from functools import cached_property
3
2
  from queue import Queue
4
3
 
4
+ from .has_thread import HasThread
5
+
5
6
 
6
7
  class ThreadQueue(HasThread):
7
8
  maxsize = 0
8
9
  thread_count = 1
9
10
  callback = print
10
11
  thread = None
12
+ name = 'thread_queue'
11
13
 
12
14
  def _start(self):
13
15
  [t.start() for t in self.threads]
@@ -1,7 +1,9 @@
1
- import datacls
2
1
  import heapq
3
2
  import time
4
- from . thread_queue import HasThread
3
+
4
+ import datacls
5
+
6
+ from .thread_queue import HasThread
5
7
 
6
8
  MAX_WAIT = 0.01
7
9
 
@@ -24,6 +26,7 @@ class TimedHeap(HasThread):
24
26
 
25
27
  def pop(self, timestamp=None):
26
28
  with self._lock:
29
+
27
30
  def top():
28
31
  return self.heap[0].timestamp if self.heap else None
29
32
 
@@ -0,0 +1,55 @@
1
+ [project]
2
+ name = "litoid"
3
+ version = "0.2.0"
4
+ description = "💡Sequence DMX lighting 💡"
5
+ authors = [{ name = "Tom Ritchford", email = "tom@swirly.com" }]
6
+ requires-python = ">=3.11"
7
+ readme = "README.md"
8
+ license = "MIT"
9
+ classifiers = ["Programming Language :: Python :: 3", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3.14"]
10
+ dependencies = [
11
+ "python-osc>=1.8.1",
12
+ "datacls>=4.6.0",
13
+ "mido>=1.2.10",
14
+ "tomlkit>=0.11.6",
15
+ "numpy>=1.24.2",
16
+ "pynput>=1.7.6",
17
+ "python-rtmidi>=1.5.4",
18
+ "xmod>=1.4.0",
19
+ "pyenttec>=1.4",
20
+ "typer>=0.7.0",
21
+ "dtyper>=2.1.0",
22
+ "pysimplegui",
23
+ "psgdemos>=1.12.1",
24
+ "pyperclip>=1.8.2",
25
+ "simpleaudio>=1.0.4",
26
+ "ipython>=8.12.0",
27
+ "clsprop>=1.1.0",
28
+ "matplotlib>=3.7.1",
29
+ "distinctipy>=1.2.2",
30
+ "coverage>=7.3.2,<8",
31
+ ]
32
+
33
+ [dependency-groups]
34
+ dev = [
35
+ "pytest",
36
+ "impall",
37
+ "coverage>=7.13.2",
38
+ "pyupgrade>=3.21.2",
39
+ "ruff>=0.14.14",
40
+ "ty>=0.0.14",
41
+ ]
42
+
43
+ [tool.uv.build-backend]
44
+ module-root = ""
45
+
46
+
47
+ [tool.coverage]
48
+
49
+ [tool.ruff.format]
50
+ quote-style = "single"
51
+ [build-system]
52
+ requires = ["uv_build>=0.9.0,<0.10.0"]
53
+ build-backend = "uv_build"
54
+
55
+
litoid-0.1.0/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2023 Tom Ritchford
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
litoid-0.1.0/PKG-INFO DELETED
@@ -1,35 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: litoid
3
- Version: 0.1.0
4
- Summary: 💡Sequence DMX lighting 💡
5
- License: MIT
6
- Author: Tom Ritchford
7
- Author-email: tom@swirly.com
8
- Requires-Python: >=3.11
9
- Classifier: License :: OSI Approved :: MIT License
10
- Classifier: Programming Language :: Python :: 3
11
- Classifier: Programming Language :: Python :: 3.11
12
- Requires-Dist: clsprop (>=1.1.0)
13
- Requires-Dist: datacls (>=4.6.0)
14
- Requires-Dist: distinctipy (>=1.2.2)
15
- Requires-Dist: dtyper (>=2.1.0)
16
- Requires-Dist: ipython (>=8.12.0)
17
- Requires-Dist: matplotlib (>=3.7.1)
18
- Requires-Dist: mido (>=1.2.10)
19
- Requires-Dist: numpy (>=1.24.2)
20
- Requires-Dist: psgdemos (>=1.12.1)
21
- Requires-Dist: pyenttec (>=1.4)
22
- Requires-Dist: pynput (>=1.7.6)
23
- Requires-Dist: pyperclip (>=1.8.2)
24
- Requires-Dist: pysimplegui (>=4.60.4)
25
- Requires-Dist: python-osc (>=1.8.1)
26
- Requires-Dist: python-rtmidi (>=1.5.4)
27
- Requires-Dist: simpleaudio (>=1.0.4)
28
- Requires-Dist: tomlkit (>=0.11.6)
29
- Requires-Dist: typer (>=0.7.0)
30
- Requires-Dist: xmod (>=1.4.0)
31
- Description-Content-Type: text/markdown
32
-
33
- # litoid
34
- Sequence DMX lighting
35
-
@@ -1,3 +0,0 @@
1
- __all__ = 'MidiInput',
2
-
3
- from . midi import MidiInput
@@ -1,38 +0,0 @@
1
- [tool.poetry]
2
- name = "litoid"
3
- version = "0.1.0"
4
- description = "💡Sequence DMX lighting 💡"
5
- authors = ["Tom Ritchford <tom@swirly.com>"]
6
- license = "MIT"
7
- readme = "README.md"
8
-
9
- [tool.poetry.dependencies]
10
- python = ">=3.11"
11
- python-osc = ">=1.8.1"
12
- datacls = ">=4.6.0"
13
- mido = ">=1.2.10"
14
- tomlkit = ">=0.11.6"
15
- numpy = ">=1.24.2"
16
- pynput = ">=1.7.6"
17
- python-rtmidi = ">=1.5.4"
18
- xmod = ">=1.4.0"
19
- pyenttec = ">=1.4"
20
- typer = ">=0.7.0"
21
- dtyper = ">=2.1.0"
22
- pysimplegui = ">=4.60.4"
23
- psgdemos = ">=1.12.1"
24
- pyperclip = ">=1.8.2"
25
- simpleaudio = ">=1.0.4"
26
- ipython = ">=8.12.0"
27
- clsprop = ">=1.1.0"
28
- matplotlib = ">=3.7.1"
29
- distinctipy = ">=1.2.2"
30
-
31
- [tool.poetry.group.dev.dependencies]
32
- flake8 = "*"
33
- pytest = "*"
34
- impall = "*"
35
-
36
- [build-system]
37
- requires = ["poetry-core"]
38
- build-backend = "poetry.core.masonry.api"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -1,6 +1,6 @@
1
- from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
2
1
  import matplotlib.pyplot as plt
3
2
  import numpy as np
3
+ from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
4
4
 
5
5
  CANVAS_KEY = 'data.canvas'
6
6
 
File without changes
File without changes
File without changes