mik3y / pymidi Goto Github PK
View Code? Open in Web Editor NEWPython library for building RTP-MIDI / AppleMIDI clients and servers
License: MIT License
Python library for building RTP-MIDI / AppleMIDI clients and servers
License: MIT License
Is it possible that you could make an example of how one could use this to communicate with for example Tobias Erichsen rtpMidi (https://www.tobias-erichsen.de/software/rtpmidi.html)
I get this every few seconds
WARNING:pymidi.ControlProtocol:Ignoring unrecognized command: b'IN'
WARNING:pymidi.ControlProtocol:Ignoring unrecognized command: b'BY'
Setting verbose mode crashes server:
Traceback (most recent call last):
File "pymidi/server.py", line 157, in <module>
server.serve_forever()
File "pymidi/server.py", line 117, in serve_forever
proto.handle_message(buffer, addr)
File "/home/fakeusername/myvenv/lib/python3.6/site-packages/pymidi-0.3.0-py3.6.egg/pymidi/protocol.py", line 70, in handle_message
self.logger.debug('rx: {}'.format(data.encode('hex')))
AttributeError: 'bytes' object has no attribute 'encode'
I'm connecting rtpMIDI tool by Tobias Erichsen from a Windows machine
also TouchDaw from an Android device. Both cause same errors.
I'm looking at line 156 of protocol.py:
now = int(time.time() * 10000)
I know that the standard says that this field is in increments of microseconds, etc. However:
The timestamp in the RTP header is only 32 bits. And the timestamps in each MIDI message that is sent are relative to the timestamps that are negotiated in the original "hello" phase of the session. I know that the RTP MIDI spec calls for 64 bit precision but that can't be right (except during the initial negotiation).
I've done some testing and bunch of packet captures between various different RTP MIDI handlers - so the timestamp might well be in microsecond increments but it has to be round down somehow. The Wikipedia article does say that:
this is not an absolute time, but a time related to a local reference
When I take out the * 10000
all of a sudden all my connections start working. So this is a good thing! ;-)
Anyway. The Linux 32 epoch is also coming up soon so I think that what is needed is to take the time, multiply by 10,000 then mod it by a specific (but constant) value. And this is going to be true everywhere in the code where the timestamp is put into the RTP header.
I'm happy to create a PR for this if you agree (I think it's kind of a big deal to be stumbling around inside the code this much).
cloned the code and tried server.py using default port and also port 2000 (as many others that are not in use).
Results:
$ python3 server.py --port 2000
INFO:pymidi.server:Data socket on 0.0.0.0:2001
INFO:pymidi.server:Control socket on 0.0.0.0:2000
INFO:pymidi.server:Data socket on :::2001
Traceback (most recent call last):
File "server.py", line 157, in <module>
server.serve_forever()
File "server.py", line 108, in serve_forever
self._init_protocols()
File "server.py", line 100, in _init_protocols
data_protocol = self._build_data_protocol(host, family)
File "server.py", line 95, in _build_data_protocol
data_socket.bind((host, self.port + 1))
OSError: [Errno 98] Address already in use
Under some circumstances (it seems when there are many packets in flight from a remote peer) there is an exception raised:
Traceback (most recent call last):
File "/home/ubuntu/python/construct/lib/containers.py", line 93, in __getattr__
return self[name]
KeyError: '_last_command_byte'
I can see in the code where this is being used but I don't have enough knowledge to figure out how to solve this.
If a computer name has an apostrophe in the invitation packet, pymidi will crash with a UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 6: ordinal not in range(128)
in the handle_message()
function.
Traceback (most recent call last):
File "server.py", line 250, in <module>
server.serve_forever()
File "server.py", line 152, in serve_forever
self._loop_once()
File "server.py", line 147, in _loop_once
proto.handle_message(buffer, addr)
File "/usr/local/lib/python3.7/site-packages/pymidi/protocol.py", line 76, in handle_message
self.handle_command_message(command, data, addr)
File "/usr/local/lib/python3.7/site-packages/pymidi/protocol.py", line 87, in handle_command_message
packet = packets.AppleMIDIExchangePacket.parse(data)
File "/usr/local/lib/python3.7/site-packages/construct/core.py", line 304, in parse
return self.parse_stream(io.BytesIO(data), **contextkw)
File "/usr/local/lib/python3.7/site-packages/construct/core.py", line 316, in parse_stream
return self._parsereport(stream, context, "(parsing)")
File "/usr/local/lib/python3.7/site-packages/construct/core.py", line 328, in _parsereport
obj = self._parse(stream, context, path)
File "/usr/local/lib/python3.7/site-packages/construct/core.py", line 1979, in _parse
subobj = sc._parsereport(stream, context, path)
File "/usr/local/lib/python3.7/site-packages/construct/core.py", line 328, in _parsereport
obj = self._parse(stream, context, path)
File "/usr/local/lib/python3.7/site-packages/construct/core.py", line 2468, in _parse
return self.subcon._parsereport(stream, context, path)
File "/usr/local/lib/python3.7/site-packages/construct/core.py", line 328, in _parsereport
obj = self._parse(stream, context, path)
File "/usr/local/lib/python3.7/site-packages/construct/core.py", line 3480, in _parse
obj = sc._parsereport(stream, context, path)
File "/usr/local/lib/python3.7/site-packages/construct/core.py", line 328, in _parsereport
obj = self._parse(stream, context, path)
File "/usr/local/lib/python3.7/site-packages/construct/core.py", line 715, in _parse
return self._decode(obj, context, path)
File "/usr/local/lib/python3.7/site-packages/construct/core.py", line 1490, in _decode
return obj.decode(self.encoding)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 6: ordinal not in range(128)
For reference invitation packet appears as the following in wireshark
The README shows links to the developer wiki page as https://github.com/mik3y/pymidi/blob/master/wiki/Developer-MIDI-Setup which does not resolve. Links to https://github.com/mik3y/pymidi/wiki/Developer-MIDI-Setup do work though.
There is example code in the README which does not work. Code should be more like this:
from pymidi import server
class MyHandler(server.Handler):
def on_peer_connected(self, peer):
print('Peer connected: {}'.format(peer))
def on_peer_disconnected(self, peer):
print('Peer disconnected: {}'.format(peer))
def on_midi_commands(self, peer, command_list):
for command in command_list:
if command.command == 'note_on':
key = command.params.key
velocity = command.params.velocity
print('Someone hit the key {} with velocity {}'.format(key, velocity))
myServer = server.Server({('0.0.0.0', 5051)})
myServer.add_handler(MyHandler())
myServer.serve_forever()
Hey,
How does one close the socket?
Just closing it causes some program to hang.
I see some clients have some command 'BY' which might be it, but not sure how to use it
A place to drop images to use on the wiki, since oddly enough Github wiki doesn't have built-in image support.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.