FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
python-osc/pythonosc/osc_server.py at master · nocarryr/python-osc · GitHub
nocarryr
/
python-osc
Public
forked from
attwad/python-osc
Notifications
You must be signed in to change notification settings
Fork
0
Star
0
Code
Pull requests
0
Actions
Projects
Wiki
Security and quality
0
Insights
Additional navigation options
Code
Pull requests
Actions
Projects
Wiki
Security and quality
Insights
Expand file tree
Breadcrumbs
python-osc
/
pythonosc
/
osc_server.py
Copy path
More file actions
More file actions
Latest commit
History
History
History
150 lines (108 loc) · 4.94 KB
Breadcrumbs
python-osc
/
pythonosc
/
osc_server.py
Copy path
File metadata and controls
150 lines (108 loc) · 4.94 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
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
"""OSC Servers that receive UDP packets and invoke handlers accordingly.
"""
import
asyncio
import
os
import
socketserver
from
pythonosc
import
osc_bundle
from
pythonosc
import
osc_message
from
pythonosc
.
dispatcher
import
Dispatcher
from
asyncio
import
BaseEventLoop
from
typing
import
List
,
Tuple
from
types
import
coroutine
class
_UDPHandler
(
socketserver
.
BaseRequestHandler
):
"""Handles correct UDP messages for all types of server."""
def
handle
(
self
)
->
None
:
"""Calls the handlers via dispatcher
This method is called after a basic sanity check was done on the datagram,
whether this datagram looks like an osc message or bundle.
If not the server won't call it and so no new
threads/processes will be spawned.
"""
self
.
server
.
dispatcher
.
call_handlers_for_packet
(
self
.
request
[
0
],
self
.
client_address
)
def
_is_valid_request
(
request
:
List
[
bytes
])
->
bool
:
"""Returns true if the request's data looks like an osc bundle or message.
Returns:
True if request is OSC bundle or OSC message
"""
data
=
request
[
0
]
return
(
osc_bundle
.
OscBundle
.
dgram_is_bundle
(
data
)
or
osc_message
.
OscMessage
.
dgram_is_message
(
data
))
class
OSCUDPServer
(
socketserver
.
UDPServer
):
"""Superclass for different flavors of OSC UDP servers"""
def
__init__
(
self
,
server_address
:
Tuple
[
str
,
int
],
dispatcher
:
Dispatcher
)
->
None
:
"""Initialize
Args:
server_address: IP and port of server
dispatcher: Dispatcher this server will use
"""
super
().
__init__
(
server_address
,
_UDPHandler
)
self
.
_dispatcher
=
dispatcher
def
verify_request
(
self
,
request
:
List
[
bytes
],
client_address
:
Tuple
[
str
,
int
])
->
bool
:
"""Returns true if the data looks like a valid OSC UDP datagram
Args:
request: Incoming data
client_address: IP and port of client this message came from
Returns:
True if request is OSC bundle or OSC message
"""
return
_is_valid_request
(
request
)
@
property
def
dispatcher
(
self
)
->
Dispatcher
:
return
self
.
_dispatcher
class
BlockingOSCUDPServer
(
OSCUDPServer
):
"""Blocking version of the UDP server.
Each message will be handled sequentially on the same thread.
Use this is you don't care about latency in your message handling or don't
have a multiprocess/multithread environment.
"""
class
ThreadingOSCUDPServer
(
socketserver
.
ThreadingMixIn
,
OSCUDPServer
):
"""Threading version of the OSC UDP server.
Each message will be handled in its own new thread.
Use this when lightweight operations are done by each message handlers.
"""
if
hasattr
(
os
,
"fork"
):
class
ForkingOSCUDPServer
(
socketserver
.
ForkingMixIn
,
OSCUDPServer
):
"""Forking version of the OSC UDP server.
Each message will be handled in its own new process.
Use this when heavyweight operations are done by each message handlers
and forking a whole new process for each of them is worth it.
"""
class
AsyncIOOSCUDPServer
():
"""Asynchronous OSC Server
An asynchronous OSC Server using UDP. It creates a datagram endpoint that runs in an event loop.
"""
def
__init__
(
self
,
server_address
:
Tuple
[
str
,
int
],
dispatcher
:
Dispatcher
,
loop
:
BaseEventLoop
)
->
None
:
"""Initialize
Args:
server_address: IP and port of server
dispatcher: Dispatcher this server shall use
loop: Event loop to add the server task to. Use ``asyncio.get_event_loop()`` unless you know what you're
doing.
"""
self
.
_server_address
=
server_address
self
.
_dispatcher
=
dispatcher
self
.
_loop
=
loop
class
_OSCProtocolFactory
(
asyncio
.
DatagramProtocol
):
"""OSC protocol factory which passes datagrams to dispatcher"""
def
__init__
(
self
,
dispatcher
:
Dispatcher
)
->
None
:
self
.
dispatcher
=
dispatcher
def
datagram_received
(
self
,
data
:
bytes
,
client_address
:
Tuple
[
str
,
int
])
->
None
:
self
.
dispatcher
.
call_handlers_for_packet
(
data
,
client_address
)
def
serve
(
self
)
->
None
:
"""Creates a datagram endpoint and registers it with event loop.
Use this only in synchronous code (i.e. not from within a coroutine). This will start the server and run it
forever or until a ``stop()`` is called on the event loop.
"""
self
.
_loop
.
run_until_complete
(
self
.
create_serve_endpoint
())
def
create_serve_endpoint
(
self
)
->
coroutine
:
"""Creates a datagram endpoint and registers it with event loop as coroutine.
Returns:
Awaitable coroutine that returns transport and protocol objects
"""
return
self
.
_loop
.
create_datagram_endpoint
(
lambda
:
self
.
_OSCProtocolFactory
(
self
.
dispatcher
),
local_addr
=
self
.
_server_address
)
@
property
def
dispatcher
(
self
)
->
Dispatcher
:
return
self
.
_dispatcher
Back
|
FazBrowse Home
|
New Git URL