Protocol::OSC(3pm) | User Contributed Perl Documentation | Protocol::OSC(3pm) |
Protocol::OSC - Open Sound Control v1.1 implementation
my $osc = Protocol::OSC->new; my $data = $osc->message(qw(/echo isf 3 ping 3.14)); # pack my $packet = $osc->parse($data); # parse $osc->actions->{$path} = $code_ref; # add callback $packet->process($data, $scheduler_coderef); # parse and execute callbacks
This module implements (de)coding and processing of OSC packets according the specification. It's pure Perl implementation, yet faster than Net::LibLO and Net::OpenSoundControl (~2x). Also it provides connection agnostic interface and path matching and type tagging according OSC v1 specification <http://opensoundcontrol.org/spec-1_0> ( and v1.1 <http://opensoundcontrol.org/spec-1_1> )
Creates Protocol::Instance with optional "actions" argument which is hashref of pairs: path => coderef and optional default scheduler for "process" method - see below.
Encodes message to packet. Typetag supports these OSC-types: ifstdbht. Everything else (like TFNI) will not affect packing of @args. Alias: msg
Encodes bundle to packet. Pack several OSC messages/bundles to a bundle.
Parses OSC packet data. Returns OSC message/bundle. OSC-message is a blessed arrayref [$path, $type, @args] with corresponding methods path, type, args. OSC-bundle is a blessed arrayref [$time, @packets] with corresponding methods time, packets
Parses OSC packet/data and process messages in it. It will call matched actions through $scheduler_cb which is just "sub { $_[0]->(splice @_,1) }" by default(or specified in constructor). Arguments to scheduler are $action_coderef, $time, $action_path, $osc_msg, ?@osc_bundles.
Returns hashref of actions: path => coderef pairs. One could modify this hashref or use methods below.
Set coderef $cb to actions
Remove coderef at $path from actions at $path
Returns mathched actions in form of list of arrayrefs [$path, $coderef]
Converts (fractional) unix epoch time to NTP timestamp, which is list of ($seconds_since_1900_01_01, $int32_fraction_parts_of_second). If $unix_time is undef then (0,1) is returned which means immediate execution by OSC specs.
Reverse of previous.
Packs raw OSC data for (tcp) streaming.
Returns list of raw OSC data packets in $buf from stream buffer and residue of $buf. If $buf is incomplete - returns only $buf.
make packet
my $data = $osc->message(my @specs = qw(/echo isf 3 ping 3.14)); # or use Time::HiRes 'time'; my $data $osc->bundle(time, [@specs], [@specs2], ...);
via UDP
my $udp = IO::Socket::INET->new( PeerAddr => 'localhost', PeerPort => $port, Proto => 'udp', Type => SOCK_DGRAM) || die $!; $udp->send($data);
via TCP
my $tcp = IO::Socket::INET->new( PeerAddr => 'localhost', PeerPort => $port, Proto => 'tcp', Type => SOCK_STREAM) || die $!; $tcp->syswrite($osc->to_stream($data));
UDP
my $in = IO::Socket::INET->new( qw(LocalAddr localhost LocalPort), $port, qw(Proto udp Type), SOCK_DGRAM ) || die $!; $in->recv(my $packet, $in->sockopt(SO_RCVBUF)); my $p = $osc->parse($packet);
TCP
my $in = IO::Socket::INET->new( qw(LocalAddr localhost LocalPort), $port, qw(Proto tcp Type), SOCK_STREAM, qw(Listen 1 Reuse 1) ) || die $!; while (my $sock = $in->accept) { my $tail; while ($sock->sysread(my $buf, $in->sockopt(SO_RCVBUF))) { my @packets = $p->from_stream(length($tail) ? $tail.$buf : $buf); $tail = pop @packets; $osc->parse($_) for @packets; } }
$osc->set_cb('/echo', sub { my ($at_time, $path, $msg, @maybe_bundles) = @_; say $at_time if $at_time; # time of parent bundle if message comes from bundle(s) say $path; # matched path say $msg->path; # path pattern of OSC message say $msg->type; # typetag say @{$msg->args}; # message arguments map { # all bundles from which $msg comes (from inner to outer) say $_->time; # time of bundle say $_->packets; # array of messages/bundle in bundle } @maybe_bundles; }); ... $osc->process($osc->parse($data));
use AnyEvent::Handle::UDP; my $udp_handle = AnyEvent::Handle::UDP->new( bind => [0, $port], on_recv => sub { my ($data, $handle, $client_addr) = @_; my $msg = $osc->parse($data); say $msg->path; $handle->push_send($osc->message(qw(/pong i), ($msg->args)[0]), $client_addr) if $msg->path eq '/ping'; } ); $udp_handle->push_send($osc->message(qw(/ping i 3)), [0, $port]);
encode
cmpthese -1, { 'Net::LibLO::Message' => sub { Net::LibLO::Message->new(qw(isf 3 laaaa 3.0)) }, 'Protocol::OSC' => sub { $protocol->message(qw(/echo isf 3 laaaa 3.0)) }, 'Net::OpenSoundControl' => sub { Net::OpenSoundControl::encode([qw(/echo i 3 s laaaa f 3.0)]) } }; ... Rate Net::LibLO::Message Net::OpenSoundControl Protocol::OSC Net::LibLO::Message 20479/s -- -7% -51% Net::OpenSoundControl 21920/s 7% -- -48% Protocol::OSC 41754/s 104% 90% --
decode
cmpthese -1, { 'Protocol::OSC' => sub { $protocol->parse($data) }, 'Net::OpenSoundControl' => sub { Net::OpenSoundControl::decode($data) } }; Rate Net::OpenSoundControl Protocol::OSC Net::OpenSoundControl 1630/s -- -65% Protocol::OSC 4654/s 186% --
No validation checks performed
<http://github.com/vividsnow/Protocol-OSC>
<https://metacpan.org/module/Protocol::OSC>
Yegor Korablev <egor@cpan.org>
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.
more docs, examples and tests.. as usual )
Net::LibLO, Net::OpenSoundControl, AnyEvent::Handle::UDP
2018-12-21 | perl v5.28.1 |