1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311
|
.. SPDX-FileCopyrightText: 2013 Ole Martin Bjorndalen <ombdalen@gmail.com>
..
.. SPDX-License-Identifier: CC-BY-4.0
Ports
=====
A Mido :term:`port` is an *object* that can *send* and/or *receive* messages.
You can open a :term:`port` by calling one of the *open methods*, for example::
>>> inport = mido.open_input('SH-201')
>>> outport = mido.open_output('Integra-7')
Now you can *receive* messages on the *input port* and *send* messages on
the *output port*::
>>> msg = inport.receive()
>>> outport.send(msg)
The message is copied by ``send()``, so you can safely modify your
original message without causing breakage in other parts of the
system.
In this case, the ports are device ports, and are connected to some
sort of (physical or virtual) MIDI device, but a port can be
anything. For example, you can use a ``MultiPort`` to receive messages
from multiple ports as if they were one::
from mido.ports import MultiPort
...
multi = MultiPort([inport1, inport2, inport3])
for msg in multi:
print(msg)
This will receive messages from all ports and print them out. Another
example is a socket port, which is a wrapper around a TCP/IP socket.
No matter how the port is implemented internally or what it does, it
will look and behave like any other Mido port, so all kinds of ports
can be used interchangeably.
.. warning:: Sending and receiving messages is thread safe. Opening and
closing ports and listing port names are not.
Common
------
How to open a :term:`port` depends on the port type. Device ports (PortMidi,
RtMidi and others defined in backends) are opened with the open
functions, for example::
port = mido.open_output()
Input and I/O ports (which support both input and output) are opened
with ``open_input()`` and ``open_ioport()`` respectively. If you call
these without a port name like above, you will get the - system
specific - default port. You can override this by setting the
``MIDO_DEFAULT_OUTPUT`` etc. environment variables.
To get a *list* of available ports, you can do::
>>> mido.get_output_names()
['SH-201', 'Integra-7']
and then::
>>> port = mido.open_output('Integra-7')
There are corresponding functions for input and I/O ports.
To learn how to open other kinds of ports, see documentation of
the relevant port type.
The *port name* is available in ``port.name``.
To *close* a port, call::
port.close()
or use the ``with`` statement to have the port closed automatically::
with mido.open_input() as port:
for message in port:
do_something_with(message)
You can check if the *port is closed* with::
if port.closed:
print("Yup, it's closed.")
If the port is already closed, calling ``close()`` will simply do nothing.
Output
------
Output :term:`ports` basically only have one method::
outport.send(message)
This will *send* the message immediately. (Well, the port can choose to
do whatever it wants with the message, but at least it's sent from Mido's
point of view.)
There are also a couple of utility methods::
outport.reset()
This will send "all notes off" and "reset all controllers" on every
channel. This is used to reset everything to the default state, for
example after playing back a song or messing around with controllers.
If you pass ``autoreset=True`` to the constructor, ``reset()`` will be
called when the port closes::
with mido.open_output('Integra-7') as outport:
for msg in inport:
outport.send(msg)
# reset() is called here
outport.close() # or here
Sometimes notes hang because a ``note_off`` has not been sent. To
(abruptly) stop all sounding notes, you can call::
outport.panic()
This will not reset controllers. Unlike ``reset()``, the notes will
not be turned off gracefully, but will stop immediately with no regard
to decay time.
Input
-----
To *iterate* over *incoming messages*::
for msg in port:
print(msg)
This will iterate over messages as they arrive on the port until the
port closes. (So far only socket ports actually close by
themselves. This happens if the other end disconnects.)
You can also do *non-blocking iteration*::
for msg in port.iter_pending():
print(msg)
This will iterate over all messages that have already arrived. It is
typically used in main loops where you want to do something else while
you wait for messages::
while True:
for msg in port.iter_pending():
print(msg)
do_other_stuff()
In an *event based system* like a GUI where you don't write the main
loop you can install a *handler* that's called periodically. Here's an
example for GTK::
def callback(self):
for msg in self.inport:
print(msg)
gobject.timeout_add_seconds(timeout, callback)
To get a bit more control you can receive messages *one at a time*::
msg = port.receive()
This will *block* until a message arrives. To get a message only if one
is available, you can use `poll()`::
msg = port.poll()
This will return ``None`` immediately if *no message is available*.
.. deprecated:: 1.2
There used to be a ``pending()`` method which returned the number of
pending messages.
It was removed for three reasons:
* with ``poll()`` and ``iter_pending()`` it is no longer
necessary
* it was unreliable when multithreading and for some ports
it doesn't even make sense
* it made the internal method API confusing. `_send()` sends
a message so `_receive()` should receive a message.
Callbacks
---------
Instead of manually reading from the :term:`port` you can install a
:term:`callback` function which will be called for every message that arrives.
Here's a simple callback function::
def print_message(message):
print(message)
To *install* the callback you can either pass it when you create the
port or later by setting the ``callback`` attribute::
port = mido.open_input(callback=print_message)
port.callback = print_message
...
port.callback = another_function
.. warning::
Since the :term:`callback` runs in a different thread you may need to use
locks or other synchronization mechanisms to keep your main program and
the callback from stepping on each other's toes.
Calling ``receive()``, ``__iter__()``, or ``iter_pending()`` on a :term:`port`
with a :term:`callback` will raise an exception::
ValueError: a callback is set for this port
To *clear* the :term:`callback`::
port.callback = None
This will return the :term:`port` to normal.
API
---
.. todo:: Add abstract code to describe these interfaces.
Common Methods and Attributes
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
``close()``
Closes the :term:`port`. If the :term:`port` is already closed this will
simply do nothing.
``name``
Name of the port or ``None``.
``closed``
``True`` if the port is closed.
Output Port Methods
^^^^^^^^^^^^^^^^^^^
``send(message)``
Sends a message.
``reset()``
Sends "all notes off" and "reset all controllers" on all channels.
``panic()``
Sends "all sounds off" on all channels. This will abruptly end all
sounding notes.
Input Port Methods
^^^^^^^^^^^^^^^^^^
``receive(block=True)``
Receives a message. This will block until it returns a message. If
``block=False`` is passed it will instead return ``None`` if there is
no message.
``poll()``
Returns a message, or ``None`` if there are no pending messages.
``iter_pending()``
Iterates through pending messages.
``__iter__()``
Iterates through messages as they arrive on the :term:`port` until the
:term:`port` closes.
.. include:: socket.rst
.. include:: custom.rst
|