VOOZH about

URL: https://manpages.org/protocolosc/3

⇱ man Protocol::OSC (3): Open Sound Control v1.1 implementation


Protocol::OSC(3) Open Sound Control v1.1 implementation

SYNOPSIS


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

DESCRIPTION

This module implements (de)coding and processing of 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 v1 specification <http://opensoundcontrol.org/spec-1_0> ( and v1.1 <http://opensoundcontrol.org/spec-1_1> )

CONSTRUCTOR

new( ?actions => {}, ?scheduler => sub {...} )

Creates Protocol::Instance with optional ``actions'' argument which is hashref of pairs: path => coderef and optional default scheduler for ``process'' method - see below.

METHODS

message($path, $typetag, ?@args)

Encodes message to packet. Typetag supports these OSC-types: ifstdbht. Everything else (like ) will not affect packing of @args. Alias: msg

bundle(undef || $unix_time, [@message_or_bundle], ...)

Encodes bundle to packet. Pack several messages/bundles to a bundle.

parse($data)

Parses packet data. Returns 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

process($data, ?$scheduler_cb)

Parses packet/data and process messages in it. It will call matched actions through $scheduler_cb which is just by default(or specified in constructor). Arguments to scheduler are $action_coderef, $time, $action_path, $osc_msg, ?@osc_bundles.

actions

Returns hashref of actions: path => coderef pairs. One could modify this hashref or use methods below.

set_cb($path, $cb)

Set coderef $cb to actions

del_cb($path)

Remove coderef at $path from actions at $path

match($osc_path_pattern)

Returns mathched actions in form of list of arrayrefs [$path, $coderef]

time2tag($unix_time)

Converts (fractional) unix epoch time to 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 specs.

tag2time($ntp_time, $fraction_of_sec)

Reverse of previous.

to_stream($data)

Packs raw data for (tcp) streaming.

from_steam($buf)

Returns list of raw data packets in $buf from stream buffer and residue of $buf.

EXAMPLES

Sending

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

 my $udp = IO::Socket::INET->new( PeerAddr => 'localhost', PeerPort => '57120', Proto => 'udp', Type => SOCK_DGRAM) || die $!;
 $udp->send($data);

via

 my $tcp = IO::Socket::INET->new( PeerAddr => 'localhost', PeerPort => '57120', Proto => 'tcp', Type => SOCK_STREAM) || die $!;
 $tcp->send($osc->to_stream($data));

Receiving

 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);
 $in = IO::Socket::INET->new( qw(LocalAddr localhost LocalPort), $port, qw(Proto tcp Type), SOCK_STREAM, qw(Listen 1 Reuse 1) ) || die $!;
 $in->accept->recv(my $packet, $in->sockopt(SO_RCVBUF));
 my $p = $osc->parse(($osc->from_stream($packet))[0]);

Dispatching

 $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));

Ping-Pong using AnyEvent::Handle::UDP

 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]);

Benchmarks

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

AUTHOR

Yegor Korablev <[email protected]>

LICENSE

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.

TODO

more docs, examples and tests.. as usual )