This file is indexed.

/usr/share/perl5/Protocol/OSC.pod is in libprotocol-osc-perl 0.08-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
=encoding utf8

=head1 NAME

Protocol::OSC - Open Sound Control v1.1 implementation

=head1 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

=head1 DESCRIPTION

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;
    });
    ...
    $osc->process($osc->parse($data));

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

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

=head2 NB

No validation checks performed

=head1 SUPPORT

=over

=item * GitHub

L<http://github.com/vividsnow/Protocol-OSC>

=item * Search MetaCPAN

L<https://metacpan.org/module/Protocol::OSC>

=back

=head1 AUTHOR

Yegor Korablev <egor@cpan.org>

=head1 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.

=head1 TODO

more docs, examples and tests.. as usual )

=head1 SEE ALSO

L<Net::LibLO>, L<Net::OpenSoundControl>, L<AnyEvent::Handle::UDP>

=cut