Skip to content

Commit 7b5d8ea

Browse files
Bob HaddletonBob Haddleton
authored andcommitted
cleanup mypy errors, address review comments, add response support to UDP server
1 parent d89c241 commit 7b5d8ea

20 files changed

Lines changed: 767 additions & 367 deletions

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
55

66
## [Unreleased]
77

8+
- Added TCP Client and Server support for OSC 1.0 and OSC 1.1 formats, with support for sending responses to the client
9+
- Added response support to the existing UDP Client and Server code
10+
811
## [1.8.3]
912

1013
- Using trusted publisher setup to publish to pypi

docs/client.rst

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
Client
22
========
33

4-
The client allows you to connect and send messages to an OSC server. The client class expects an :class:`OSCMessage` object, which is then sent out via UDP. Additionally, a simple client class exists that constructs the :class:`OSCMessage` object for you.
4+
The client allows you to connect and exchange messages with an OSC server.
5+
Client classes are available for UDP and TCP protocols.
6+
The base client class ``send`` method expects an :class:`OSCMessage` object, which is then sent out over TCP or UDP.
7+
Additionally, a simple client class exists that constructs the :class:`OSCMessage` object for you.
58

6-
Example
9+
See the examples folder for more use cases.
10+
11+
Examples
712
---------
813

914
.. code-block:: python
@@ -19,10 +24,27 @@ Example
1924
client.send_message("/some/address", [1, 2., "hello"]) # Send message with int, float and string
2025
2126
27+
.. code-block:: python
28+
29+
from pythonosc.tcp_client import SimpleTCPClient
30+
31+
ip = "127.0.0.1"
32+
port = 1337
33+
34+
client = SimpleTCPClient(ip, port) # Create client
35+
36+
client.send_message("/some/address", 123) # Send float message
37+
client.send_message("/some/address", [1, 2., "hello"]) # Send message with int, float and string
38+
2239
Client Module Documentation
2340
---------------------------------
2441

2542
.. automodule:: pythonosc.udp_client
2643
:special-members:
2744
:members:
2845
:exclude-members: __weakref__
46+
47+
.. automodule:: pythonosc.tcp_client
48+
:special-members:
49+
:members:
50+
:exclude-members: __weakref__

docs/dispatcher.rst

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,18 @@ The handler must have the same signature as map callbacks:
117117
def some_callback(address: str, *osc_arguments: List[Any]) -> None:
118118
119119
120+
Handler Responses
121+
-----------------
122+
123+
Handler functions can return responses back to the client, when running on a server, or to the
124+
server when running as a client. Handler functions should return one of:
125+
126+
* None
127+
* An OSC address in string format
128+
* A tuple containing a string OSC address and the associated arguments
129+
130+
If the handler function response is not None it will be encoded in an OSCMessage and sent to the
131+
remote client or server.
120132

121133
Dispatcher Module Documentation
122134
---------------------------------

docs/server.rst

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ Server
22
=========
33

44
The server receives OSC Messages from connected clients and invoked the appropriate callback functions with the dispatcher. There are several server types available.
5-
5+
Server implementations are available for both UDP and TCP protocols.
66

77
Blocking Server
88
-----------------
@@ -123,6 +123,11 @@ Server Module Documentation
123123
------------------------------
124124

125125
.. automodule:: pythonosc.osc_server
126+
:special-members:
127+
:members:
128+
:exclude-members: __weakref__
129+
130+
.. automodule:: pythonosc.osc_tcp_server
126131
:special-members:
127132
:members:
128133
:exclude-members: __weakref__

examples/async_simple_tcp_client.py

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
sends 10 random values between 0.0 and 1.0 to the /filter address,
55
waiting for 1 seconds between each value in a second task.
66
"""
7+
78
import argparse
89
import asyncio
910
import random
@@ -27,19 +28,25 @@ async def send_messages(client):
2728

2829
async def init_main():
2930
parser = argparse.ArgumentParser()
30-
parser.add_argument("--ip", default="127.0.0.1",
31-
help="The ip of the OSC server")
32-
parser.add_argument("--port", type=int, default=5005,
33-
help="The port the OSC server is listening on")
34-
parser.add_argument("--mode", default="1.1",
35-
help="The OSC protocol version of the server (default is 1.1)")
31+
parser.add_argument("--ip", default="127.0.0.1", help="The ip of the OSC server")
32+
parser.add_argument(
33+
"--port", type=int, default=5005, help="The port the OSC server is listening on"
34+
)
35+
parser.add_argument(
36+
"--mode",
37+
default="1.1",
38+
help="The OSC protocol version of the server (default is 1.1)",
39+
)
3640
args = parser.parse_args()
3741

38-
async with tcp_client.AsyncSimpleTCPClient(args.ip, args.port, mode=args.mode) as client:
42+
async with tcp_client.AsyncSimpleTCPClient(
43+
args.ip, args.port, mode=args.mode
44+
) as client:
3945
async with asyncio.TaskGroup() as tg:
4046
tg.create_task(get_messages(client))
4147
tg.create_task(send_messages(client))
4248

49+
4350
if sys.version_info >= (3, 7):
4451
asyncio.run(init_main())
4552
else:

examples/async_tcp_server.py

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,20 @@ async def loop():
2323

2424
async def init_main():
2525
parser = argparse.ArgumentParser()
26-
parser.add_argument("--ip", default="127.0.0.1",
27-
help="The ip of the OSC server")
28-
parser.add_argument("--port", type=int, default=5005,
29-
help="The port the OSC server is listening on")
30-
parser.add_argument("--mode", default="1.1",
31-
help="The OSC protocol version of the server (default is 1.1)")
26+
parser.add_argument("--ip", default="127.0.0.1", help="The ip of the OSC server")
27+
parser.add_argument(
28+
"--port", type=int, default=5005, help="The port the OSC server is listening on"
29+
)
30+
parser.add_argument(
31+
"--mode",
32+
default="1.1",
33+
help="The OSC protocol version of the server (default is 1.1)",
34+
)
3235
args = parser.parse_args()
3336

34-
async with AsyncOSCTCPServer(args.ip, args.port, dispatcher, mode=args.mode) as server:
37+
async with AsyncOSCTCPServer(
38+
args.ip, args.port, dispatcher, mode=args.mode
39+
) as server:
3540
async with asyncio.TaskGroup() as tg:
3641
tg.create_task(server.start())
3742
tg.create_task(loop())

examples/simple_echo_client.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
"""Small example OSC client
2+
3+
This program sends 10 random values between 0.0 and 1.0 to the /filter address,
4+
waiting for 1 seconds between each value.
5+
"""
6+
7+
import argparse
8+
import random
9+
import time
10+
11+
from pythonosc import udp_client
12+
13+
if __name__ == "__main__":
14+
parser = argparse.ArgumentParser()
15+
parser.add_argument("--ip", default="127.0.0.1", help="The ip of the OSC server")
16+
parser.add_argument(
17+
"--port", type=int, default=5005, help="The port the OSC server is listening on"
18+
)
19+
args = parser.parse_args()
20+
21+
client = udp_client.SimpleUDPClient(args.ip, args.port)
22+
23+
for x in range(10):
24+
client.send_message("/filter", random.random())
25+
reply = next(client.get_messages(2))
26+
print(str(reply))
27+
time.sleep(1)

examples/simple_echo_server.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
"""Small example OSC server
2+
3+
This program listens to several addresses, and prints some information about
4+
received packets.
5+
"""
6+
7+
import argparse
8+
import math
9+
10+
from pythonosc.dispatcher import Dispatcher
11+
from pythonosc import osc_server
12+
13+
14+
def echo_handler(client_addr, unused_addr, args):
15+
print(unused_addr, args)
16+
return (unused_addr, args)
17+
18+
19+
if __name__ == "__main__":
20+
parser = argparse.ArgumentParser()
21+
parser.add_argument("--ip", default="127.0.0.1", help="The ip to listen on")
22+
parser.add_argument("--port", type=int, default=5005, help="The port to listen on")
23+
args = parser.parse_args()
24+
25+
dispatcher = Dispatcher()
26+
dispatcher.set_default_handler(echo_handler, True)
27+
28+
server = osc_server.ThreadingOSCUDPServer((args.ip, args.port), dispatcher)
29+
print("Serving on {}".format(server.server_address))
30+
server.serve_forever()

examples/simple_tcp_client.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,23 @@
33
This program sends 10 random values between 0.0 and 1.0 to the /filter address,
44
and listens for incoming messages for 1 second between each value.
55
"""
6+
67
import argparse
78
import random
89

910
from pythonosc import tcp_client
1011

1112
if __name__ == "__main__":
1213
parser = argparse.ArgumentParser()
13-
parser.add_argument("--ip", default="127.0.0.1",
14-
help="The ip of the OSC server")
15-
parser.add_argument("--port", type=int, default=5005,
16-
help="The port the OSC server is listening on")
17-
parser.add_argument("--mode", default="1.1",
18-
help="The OSC protocol version of the server (default is 1.1)")
14+
parser.add_argument("--ip", default="127.0.0.1", help="The ip of the OSC server")
15+
parser.add_argument(
16+
"--port", type=int, default=5005, help="The port the OSC server is listening on"
17+
)
18+
parser.add_argument(
19+
"--mode",
20+
default="1.1",
21+
help="The OSC protocol version of the server (default is 1.1)",
22+
)
1923
args = parser.parse_args()
2024

2125
with tcp_client.SimpleTCPClient(args.ip, args.port, mode=args.mode) as client:

examples/simple_tcp_server.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
This program listens to the specified address and port, and prints some information about
44
received packets.
55
"""
6+
67
import argparse
78
import math
89

@@ -23,12 +24,13 @@ def print_compute_handler(unused_addr, args, volume):
2324

2425
if __name__ == "__main__":
2526
parser = argparse.ArgumentParser()
26-
parser.add_argument("--ip",
27-
default="127.0.0.1", help="The ip to listen on")
28-
parser.add_argument("--port",
29-
type=int, default=5005, help="The port to listen on")
30-
parser.add_argument("--mode", default="1.1",
31-
help="The OSC protocol version of the server (default is 1.1)")
27+
parser.add_argument("--ip", default="127.0.0.1", help="The ip to listen on")
28+
parser.add_argument("--port", type=int, default=5005, help="The port to listen on")
29+
parser.add_argument(
30+
"--mode",
31+
default="1.1",
32+
help="The OSC protocol version of the server (default is 1.1)",
33+
)
3234

3335
args = parser.parse_args()
3436

@@ -38,6 +40,7 @@ def print_compute_handler(unused_addr, args, volume):
3840
dispatcher.map("/logvolume", print_compute_handler, "Log volume", math.log)
3941

4042
server = osc_tcp_server.ThreadingOSCTCPServer(
41-
(args.ip, args.port), dispatcher, mode=args.mode)
43+
(args.ip, args.port), dispatcher, mode=args.mode
44+
)
4245
print("Serving on {}".format(server.server_address))
4346
server.serve_forever()

0 commit comments

Comments
 (0)