Protocol::OSC(3pm)
π Protocol::OSC β the Protocol::OSC(3pm) era π
okay bestie, sit down, hydrate, because we're talking about Protocol::OSC β that's the Open Sound Control v1.1 implementation and she is literally iconic. this is the user-contributed Perl documentation page, and yes, we're reading it together, no cap. π
β¨ NAME β¨
Protocol::OSC β Open Sound Control v1.1 implementation. that's it, that's the whole vibe. π¦
πΈ SYNOPSIS πΈ
look at her. look at the lewk:
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
pack it, parse it, callback it, process it. the whole lifecycle. π
π DESCRIPTION π
so this module does the (de)coding and the processing of OSC packets according to the specification. she's a pure Perl implementation, and β not to brag but she IS going to brag β she's faster than Net::LibLO and Net::OpenSoundControl (~2x). ate and left no crumbs, fr fr. π₯
she also gives you a connection agnostic interface plus path matching and type tagging according to the OSC v1 specification <http://opensoundcontrol.org/spec-1_0> (and v1.1 <http://opensoundcontrol.org/spec-1_1>). iykyk. π
π CONSTRUCTOR π
π§ new( ?actions => {}, ?scheduler => sub {...} )
Creates Protocol::Instance with an optional "actions" argument β that's a hashref of pairs: path => coderef β and an optional default scheduler for the "process" method. see below, bestie, we get there. π«Ά
π METHODS π
message($path, $typetag, ?@args)β Encodes a message to a packet. The typetag supports these OSC-types:ifstdbht. Everything else (likeTFNI) will not affect packing of@args. Alias:msg. πbundle(undef || $unix_time, [@message_or_bundle], ...)β Encodes a bundle to a packet. Pack several OSC messages/bundles into a bundle. bundling bundle-ception, we love to see it. πparse($data)β Parses OSC packet data. Returns OSC message/bundle. An OSC-message is a blessed arrayref[$path, $type, @args]with corresponding methodspath,type,args. An OSC-bundle is a blessed arrayref[$time, @packets]with corresponding methodstime,packets. β¨process($data, ?$scheduler_cb)β Parses OSC packet/data and processes messages in it. It will call matched actions through$scheduler_cb, which is justsub { $_[0]->(splice @_,1) }by default (or whatever you specified in the constructor). Arguments to the scheduler are$action_coderef, $time, $action_path, $osc_msg, ?@osc_bundles. πactionsβ Returns hashref of actions:path => coderefpairs. One could modify this hashref or use the methods below. your call, bestie. πset_cb($path, $cb)β Set coderef$cbto actions. πdel_cb($path)β Remove coderef at$pathfrom actions at$path. bye bestie πmatch($osc_path_pattern)β Returns matched actions in form of list of arrayrefs[$path, $coderef]. πΈtime2tag($unix_time)β Converts (fractional) unix epoch time to NTP timestamp, which is a list of($seconds_since_1900_01_01, $int32_fraction_parts_of_second). If$unix_timeis undef then(0,1)is returned, which means immediate execution by OSC specs. β°tag2time($ntp_time, $fraction_of_sec)β Reverse of previous. πto_stream($data)β Packs raw OSC data for (tcp) streaming. π¦from_stream($buf)β Returns list of raw OSC data packets in$buffrom stream buffer and residue of$buf. If$bufis incomplete β returns only$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 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));
π₯ Receiving
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;
}
}
π 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% --
β οΈ NB
No validation checks performed. bestie. just so you know. the module is NOT checking your work for you. π
π«Ά SUPPORT π«Ά
- GitHub
<http://github.com/vividsnow/Protocol-OSC>
- Search MetaCPAN
<https://metacpan.org/module/Protocol::OSC>
πΈ AUTHOR πΈ
Yegor Korablev <egor@cpan.org> β the icon, the moment, the blueprint. π
π 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. slay, legally. βοΈβ¨
π TODO π
more docs, examples and tests.. as usual ) β the eternal mood, fr. π
π SEE ALSO π
Net::LibLO, Net::OpenSoundControl, AnyEvent::Handle::UDP β go read those too, bestie, expand the brain. π§ π
and that's the whole page, babes. this one shipped as perl v5.28.1 on 2018-12-21, and honestly? still giving main character energy. periodt. π ππ
π¦ where this page comes from
- debian bookworm: libprotocol-osc-perl 0.09-1 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- debian trixie: libprotocol-osc-perl 0.09-1 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- ubuntu jammy: libprotocol-osc-perl 0.09-1 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- ubuntu noble: libprotocol-osc-perl 0.09-1 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms