From 503642c024c35d7cb1bcb4322c9ce7f89a35cf84 Mon Sep 17 00:00:00 2001 From: Talley Lambert Date: Fri, 27 Oct 2023 15:20:35 -0400 Subject: [PATCH 1/3] feat: add example and do a little dance --- example.py | 23 +++++++++++++++++++++++ mini.yml | 17 +++++++++++++++++ src/pymmcore_midi/_device.py | 19 +++++++++++++++++++ src/pymmcore_midi/_xtouch.py | 10 ++++++++++ 4 files changed, 69 insertions(+) create mode 100644 example.py create mode 100644 mini.yml diff --git a/example.py b/example.py new file mode 100644 index 0000000..cdf1898 --- /dev/null +++ b/example.py @@ -0,0 +1,23 @@ +from pymmcore_plus import CMMCorePlus +from pymmcore_widgets import ImagePreview, PropertyBrowser +from qtpy.QtWidgets import QApplication + +from pymmcore_midi import DeviceMap, XTouchMini + +app = QApplication([]) + +# from pymmcore-plus +core = CMMCorePlus.instance() +core.loadSystemConfiguration() + +# this library +mini = XTouchMini() +dev_map = DeviceMap.from_file("mini.yml") +dev_map.connect_to_core(core, mini) + +# just stuff from widgets to show that it's responding +img = ImagePreview(mmcore=core) +img.show() +browser = PropertyBrowser(mmcore=core) +browser.show() +app.exec() diff --git a/mini.yml b/mini.yml new file mode 100644 index 0000000..dcf13d1 --- /dev/null +++ b/mini.yml @@ -0,0 +1,17 @@ +device_name: X-TOUCH MINI +mappings: + - [button, 8, Camera, AllowMultiROI] + - [button, 9, Camera, Binning] + - [knob, 2, Camera, Gain] + - [knob, 9, Camera, CCDTemperature] + - message_type: control_change + control_id: 1 + device_label: Camera + property_name: Exposure + - message_type: button + control_id: 22 + core_method: snap + - message_type: knob + control_id: 17 + core_method: setAutoFocusOffset + \ No newline at end of file diff --git a/src/pymmcore_midi/_device.py b/src/pymmcore_midi/_device.py index 76db5cf..034a7b7 100644 --- a/src/pymmcore_midi/_device.py +++ b/src/pymmcore_midi/_device.py @@ -1,6 +1,8 @@ from __future__ import annotations import os +import time +from threading import Thread from typing import TYPE_CHECKING, ClassVar, Iterable, Iterator, Mapping, TypeVar import mido @@ -57,6 +59,18 @@ def release(self) -> None: msg = mido.Message("note_off", channel=self._channel, note=self._note) self._output.send(msg) + def blink(self, speed: float = 0.05, repeat: int = 1) -> None: + """Blink the button on and off in another thread.""" + + def _blink(repeat: int = repeat) -> None: + for _ in range(repeat): + self.press() + time.sleep(speed) + self.release() + time.sleep(speed) + + Thread(target=_blink, daemon=True).start() + class Knob: """A knob/slider on a midi device.""" @@ -150,6 +164,7 @@ def __init__( self._buttons = Buttons(button_ids, self._output) self._knobs = Knobs(knob_ids, self._output) self._debug = debug + Thread(target=self.do_a_little_dance, daemon=True).start() @property def knob(self) -> Knobs: @@ -196,3 +211,7 @@ def reset(self) -> None: knob.set_value(0) for button in self._buttons.values(): button.release() + + def do_a_little_dance(self, *args, **kwargs) -> None: + """Flash the device's lights.""" + ... diff --git a/src/pymmcore_midi/_xtouch.py b/src/pymmcore_midi/_xtouch.py index 18b9e8d..850b74a 100644 --- a/src/pymmcore_midi/_xtouch.py +++ b/src/pymmcore_midi/_xtouch.py @@ -1,3 +1,6 @@ +import time +from itertools import chain + from ._device import Button, MidiDevice @@ -63,3 +66,10 @@ def play(self) -> Button: @property def record(self) -> Button: return self._buttons[23] + + def do_a_little_dance(self, speed: float = 0.04, repeat: int = 2) -> None: + """Flash the device's lights.""" + for _ in range(repeat): + for i in chain(range(8, 16), reversed(range(16, 24))): + self._buttons[i].blink() + time.sleep(speed) From 6b260dc3f7ec744c65ed2437289fb3231fde94d3 Mon Sep 17 00:00:00 2001 From: Talley Lambert Date: Fri, 27 Oct 2023 15:21:24 -0400 Subject: [PATCH 2/3] update readme --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index 4c178ce..73000e4 100644 --- a/README.md +++ b/README.md @@ -54,6 +54,16 @@ Now when you move a knob or press a button on your MIDI device, the corresponding property/method will be updated/called on the `CMMCorePlus` object. :tada: +## Example + +From this repo, run: + +```bash +python example.py +``` + +and adjust `mini.yml` to assign buttons + ## Debugging/Development Use the environment variable `PYMMCORE_MIDI_DEBUG=1` to print out the MIDI From 68b2de6e9f8db60e783cda1fe2a8c8ed3eeca4e8 Mon Sep 17 00:00:00 2001 From: Talley Lambert Date: Fri, 27 Oct 2023 17:11:18 -0400 Subject: [PATCH 3/3] fix lint --- src/pymmcore_midi/_device.py | 5 ++--- src/pymmcore_midi/_xtouch.py | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/pymmcore_midi/_device.py b/src/pymmcore_midi/_device.py index 034a7b7..b1fd6c5 100644 --- a/src/pymmcore_midi/_device.py +++ b/src/pymmcore_midi/_device.py @@ -212,6 +212,5 @@ def reset(self) -> None: for button in self._buttons.values(): button.release() - def do_a_little_dance(self, *args, **kwargs) -> None: - """Flash the device's lights.""" - ... + def do_a_little_dance(self) -> None: + """Do something nifty to indicate that the device is connected.""" diff --git a/src/pymmcore_midi/_xtouch.py b/src/pymmcore_midi/_xtouch.py index 850b74a..d76aa92 100644 --- a/src/pymmcore_midi/_xtouch.py +++ b/src/pymmcore_midi/_xtouch.py @@ -68,7 +68,7 @@ def record(self) -> Button: return self._buttons[23] def do_a_little_dance(self, speed: float = 0.04, repeat: int = 2) -> None: - """Flash the device's lights.""" + """Do something nifty to indicate that the device is connected.""" for _ in range(repeat): for i in chain(range(8, 16), reversed(range(16, 24))): self._buttons[i].blink()