File: intro.rst

package info (click to toggle)
python-mido 1.3.3-0.2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 920 kB
  • sloc: python: 4,006; makefile: 127; sh: 4
file content (194 lines) | stat: -rw-r--r-- 5,255 bytes parent folder | download | duplicates (2)
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
.. SPDX-FileCopyrightText: 2013 Ole Martin Bjorndalen <ombdalen@gmail.com>
..
.. SPDX-License-Identifier: CC-BY-4.0

Introduction (Basic Concepts)
=============================

Mido is all about messages, ports and files.


Messages
--------

Mido allows you to work with MIDI messages as Python objects. To
create a new message::

    >>> from mido import Message
    >>> msg = Message('note_on', note=60)
    >>> msg
    Message('note_on', channel=0, note=60, velocity=64, time=0)

.. note::

    Mido numbers channels ``0`` to ``15`` instead of ``1`` to ``16``. This makes
    them easier to work with from Python but you may want to add and subtract
    ``1`` when communicating with the user.

A list of all supported message types and their parameters can be
found in :doc:`message_types`.

The values can now be accessed as attributes::

    >>> msg.type
    'note_on'
    >>> msg.note
    60
    >>> msg.velocity
    64

Attributes are also settable but this should be avoided. It's better
to use ``msg.copy()``::

    >>> msg.copy(note=100, velocity=127)
    Message('note_on', channel=0, note=100, velocity=127, time=0)

Type and value checks are done when you pass parameters or assign to
attributes, and the appropriate exceptions are raised. This ensures
that the message is always valid.

For more about messages, see :doc:`messages/index`.


Type and Value Checking
^^^^^^^^^^^^^^^^^^^^^^^

Mido messages come with type and value checking built in::

    >>> import mido
    >>> mido.Message('note_on', channel=2092389483249829834)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "/home/olemb/src/mido/mido/messages/messages.py", line 89, in __init__
        check_msgdict(msgdict)
      File "/home/olemb/src/mido/mido/messages/checks.py", line 100, in check_msgdict
        check_value(name, value)
      File "/home/olemb/src/mido/mido/messages/checks.py", line 87, in check_value
        _CHECKS[name](value)
      File "/home/olemb/src/mido/mido/messages/checks.py", line 17, in check_channel
        raise ValueError('channel must be in range 0..15')
    ValueError: channel must be in range 0..15

This means that the message object is always a valid MIDI message.


Ports
-----

To create an output port and send a message::

    >>> outport = mido.open_output()
    >>> outport.send(msg)

To create an input port and receive a message::

    >>> inport = mido.open_input()
    >>> msg = inport.receive()

.. note::

    Multiple threads can safely send and receive notes on the same
    port.

This will give you the default output and input ports. If you want to
open a specific port, you will need its name. To get a list of all
available input ports::

    >>> mido.get_input_names()
    ['Midi Through Port-0', 'SH-201', 'Integra-7']
    >>> inport = mido.open_input('SH-201')

All Mido ports can be used with the ``with`` statement, which will
close the port for you::

    with mido.open_input('SH-201') as inport:
        ...

To iterate through all incoming messages::

    for msg in inport:
        ...

You can also receive and iterate over messages in a non-blocking
way.

For more about ports, see :doc:`ports/index`.


All Ports are Ports
^^^^^^^^^^^^^^^^^^^

The input and output ports used above are device ports, which
communicate with a physical or virtual MIDI device.

Other port types include:

* ``MultiPort``, which wraps around a set of ports and allows you to send to
  all of them or receive from all of them as if they were one.

* ``SocketPort``, which communicates with another port over a TCP/IP (network)
  connection.

* ``IOPort``, which wraps around an input and an output port and allows you to
  send and receive messages as if the two were the same port.

Ports of all types look and behave the same way, so they can be used
interchangeably.

It's easy to write new port types. See :doc:`ports/custom`.


Virtual Ports
^^^^^^^^^^^^^

Virtual ports allows you to create new ports that other applications
can connect to::

    with mido.open_input('New Port', virtual=True) as inport:
        for message in inport:
            print(message)

The port should now appear to other applications as "``New Port``".


.. warning::

    Unfortunately virtual ports are not supported by PortMidi and Pygame
    so this only works with RtMidi.

    Furthermore, RtMidi's virtual ports are not available under Microsoft
    Windows. See: :doc:`backends/rtmidi` for details.


Raw MIDI Bytes Parser
---------------------

Mido comes with a parser that allows you to turn ``bytes`` into
messages. You can create a new parser::

    >>> p = mido.Parser()
    >>> p.feed([0x90, 0x40])
    >>> p.feed_byte(0x60)

You can then fetch messages out of the parser::

    >>> p.pending()
    1
    >>> for message in p:
    ...    print(message)
    ...
    note_on channel=0 note=64 velocity=96 time=0

For more on parsers and parsing see :doc:`messages/parsing`.

.. versionadded:: 1.2

You can also create a message from ``bytes`` using class methods:

.. code-block:: python

   msg1 = mido.Message.from_bytes([0x90, 0x40, 0x60])
   msg2 = mido.Message.from_hex('90, 40 60')

The ``bytes`` must contain exactly one complete message. If not
``ValueError`` is raised.