PageRenderTime 23ms CodeModel.GetById 1ms app.highlight 17ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/Teto/Tatsumaki/Handler/Stream.pm

http://github.com/motemen/Teto
Perl | 59 lines | 49 code | 10 blank | 0 comment | 4 complexity | 24da24cb15772acb8e0149bfb237a9f8 MD5 | raw file
 1package Teto::Tatsumaki::Handler::Stream;
 2use strict;
 3use warnings;
 4use parent 'Teto::Tatsumaki::Handler';
 5use Coro;
 6
 7use Teto::Worker::ReadBuffer;
 8
 9__PACKAGE__->asynchronous(1);
10
11sub get {
12    my $self = shift;
13
14    my $control = $self->build_control;
15
16    my $icemeta = !!$self->request->header('ICY-Metadata');
17    my $read_buffer = Teto::Worker::ReadBuffer->spawn(
18        queue => $control->queue,
19        ( $icemeta ? () : ( icemeta => undef ) ),
20    );
21
22    $self->binary(1);
23    $self->response->content_type('audio/mp3');
24    $self->response->header(
25        $icemeta ? ( 'Icy-Metaint' => $read_buffer->icemeta->interval ) : (),
26        Icy_Name       => 'tetocast',
27        Icy_Url        => $self->request->uri,
28        Ice_Audio_Info => 'ice-samplerate=44100;ice-bitrate=192000;ice-channels=2',
29    );
30
31    $self->flush; # iTunes seems to disconnect if header does not return immediately
32
33    async {
34        $Coro::current->desc('streamer coro');
35
36        if ($self->get_writer->isa('Twiggy::Writer')) {
37            $self->writer->{handle}->on_drain(unblock_sub {
38                my $bytes = $read_buffer->channel->get;
39                $self->writer->write($bytes);
40            });
41            $self->writer->{handle}->on_error(sub {
42                my ($handle, $fatal, $msg) = @_;
43                $self->log($fatal ? 'error' : 'warn', $msg);
44                $self->writer->close;
45            });
46        } else {
47            while (defined (my $bytes = $read_buffer->channel->get)) {
48                eval { $self->stream_write($bytes) };
49                if ($@) {
50                    warn $@;
51                    last;
52                };
53            }
54            $self->finish;
55        }
56    };
57}
58
591;