aboutsummaryrefslogtreecommitdiffhomepage
path: root/backends/python.md
diff options
context:
space:
mode:
authorcbdev <cb@cbcdn.com>2020-03-08 13:24:33 +0100
committercbdev <cb@cbcdn.com>2020-03-08 13:24:33 +0100
commit38d3724b2af3c2b08c548326797c2421b054c846 (patch)
tree307d15dcbe27426b396f5e5f06b40bb67a8d2376 /backends/python.md
parentf9829ae90d4017940047b561e412c6eb7f431adb (diff)
downloadmidimonster-38d3724b2af3c2b08c548326797c2421b054c846.tar.gz
midimonster-38d3724b2af3c2b08c548326797c2421b054c846.tar.bz2
midimonster-38d3724b2af3c2b08c548326797c2421b054c846.zip
Implement python intervaling and socket management
Diffstat (limited to 'backends/python.md')
-rw-r--r--backends/python.md44
1 files changed, 40 insertions, 4 deletions
diff --git a/backends/python.md b/backends/python.md
index fae3139..b6a1162 100644
--- a/backends/python.md
+++ b/backends/python.md
@@ -7,6 +7,9 @@ Every instance has its own interpreter, which can be loaded with multiple Python
These modules may contain member functions accepting a single `float` parameter, which can
then be used as target channels. For each incoming event, the handler function is called.
+Python modules may also register `socket` objects (and an associated callback function) with
+the MIDIMonster core, which will then alert the module when there is data ready to be read.
+
To interact with the MIDIMonster core, import the `midimonster` module from within your module.
The `midimonster` module provides the following functions:
@@ -17,17 +20,47 @@ The `midimonster` module provides the following functions:
| `inputvalue(string)` | `midimonster.inputvalue("foo")` | Get the last input value on a channel |
| `outputvalue(string)` | `midimonster.outputvalue("bar")` | Get the last output value on a channel |
| `current()` | `print(midimonster.current())` | Returns the name of the input channel whose handler function is currently running or `None` if the interpreter was called from another context |
+| `timestamp()` | `print(midimonster.timestamp())` | Get the internal core timestamp (in milliseconds) |
+| `interval(function, long)` | `midimonster.interval(toggle, 100)` | Register a function to be called periodically. Interval is specified in milliseconds (accurate to 10msec). Calling `interval` with the same function again updates the interval. Specifying the interval as `0` cancels the interval |
+| `manage(function, socket)` | `midimonster.manage(handler, socket)`| Register a (connected/listening) socket to the MIDIMonster core. Calls `function(socket)` when the socket is ready to read. Calling this method with `None` as the function argument unregisters the socket. A socket may only have one associated handler |
Example Python module:
```
+import socket
import midimonster
+# Simple channel ahndler
def in1(value):
midimonster.output("out1", 1 - value)
+
+# Socket data handler
+def socket_handler(sock):
+ # This should get some more error handling
+ data = sock.recv(1024)
+ print("Received %d bytes from socket: %s" % (len(data), data))
+ if(len(data) == 0):
+ # Unmanage the socket if it has been closed
+ midimonster.manage(None, sock)
+ sock.close()
+
+# Interval handler
+def ping():
+ print(midimonster.interval())
+
+# Register an interval
+midimonster.interval(ping, 1000)
+# Create and register a client socket (add error handling as you like)
+s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+s.connect(("localhost", 8990))
+midimonster.manage(reader, s)
```
Input values range between 0.0 and 1.0, output values are clamped to the same range.
+Note that registered sockets that have been closed (`socket.recv()` returned 0 bytes)
+need to be unregistered from the MIDIMonster core, otherwise the core socket multiplexing
+mechanism will report an error and shut down the MIDIMonster.
+
#### Global configuration
The `python` backend does not take any global configuration.
@@ -49,7 +82,7 @@ specify the channel as the functions qualified path (by prefixing it with the mo
Example mappings:
```
py1.my_handlers.in1 < py1.foo
-py1.out1 > py2.module.handler
+py1.out1 > py2.module.handler
```
#### Known bugs / problems
@@ -57,7 +90,10 @@ py1.out1 > py2.module.handler
Output values will not trigger corresponding input event handlers unless the channel is mapped
back in the MIDIMonster configuration. This is intentional.
-Importing a Python module named `midimonster` may cause problems and is unsupported.
+Importing a Python module named `midimonster` is probably a bad idea and thus unsupported.
+
+The MIDIMonster is, at its core, single-threaded. Do not try to use Python's `threading`
+module with the MIDIMonster.
-There is currently no functionality for cyclic execution. This may be implemented in a future
-release.
+Note that executing Python code blocks the MIDIMonster core. It is not a good idea to call functions that
+take a long time to complete (such as `time.sleep()`) within your Python modules.