Protocol-OSC

 view release on metacpan or  search on metacpan

lib/Protocol/OSC.pod  view on Meta::CPAN

This module implements (de)coding and processing of OSC packets according the specification. It's pure Perl implementation, yet faster
than L<Net::LibLO> and L<Net::OpenSoundControl> (~2x). Also it provides connection agnostic interface and
path matching and type tagging according L<OSC v1 specification|http://opensoundcontrol.org/spec-1_0> ( and L<v1.1|http://opensoundcontrol.org/spec-1_1> )

=head1 CONSTRUCTOR

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

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

=head1 METHODS

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

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

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

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

=head2 parse($data)

Parses OSC packet data. Returns OSC message/bundle.
OSC-message is a blessed arrayref B<[$path, $type, @args]> with corresponding methods B<path>, B<type>, B<args>.
OSC-bundle is a blessed arrayref B<[$time, @packets]> with corresponding methods B<time>, B<packets>

=head2 process($data, ?$scheduler_cb)

Parses OSC packet/data and process messages in it. It will call matched actions through B<$scheduler_cb> which is
just C<< sub { $_[0]->(splice @_,1) } >> by default(or specified in constructor).
Arguments to scheduler are B<$action_coderef, $time, $action_path, $osc_msg, ?@osc_bundles>.

=head2 actions

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

=head2 set_cb($path, $cb)

Set coderef B<$cb> to B<actions>

=head2 del_cb($path)

Remove coderef at B<$path> from B<actions> at B<$path>

=head2 match($osc_path_pattern)

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

=head2 time2tag($unix_time)

Converts (fractional) unix epoch time to NTP timestamp, which is list of B<($seconds_since_1900_01_01, $int32_fraction_parts_of_second)>.
If B<$unix_time> is undef then (0,1) is returned which means immediate execution by OSC specs.

=head2 tag2time($ntp_time, $fraction_of_sec)

Reverse of previous.

=head2 to_stream($data)

Packs raw OSC data for (tcp) streaming.

=head2 from_stream($buf)

Returns list of raw OSC data packets in B<$buf> from stream buffer and residue of B<$buf>.
If $buf is incomplete - returns only B<$buf>.

=head1 EXAMPLES

=head2 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));

=head2 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;
        }
    }

=head2 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;



( run in 0.873 second using v1.01-cache-2.11-cpan-39bf76dae61 )