Apache-MP3
view release on metacpan or search on metacpan
# stream the indicated file
sub stream {
my $self = shift;
my $r = $self->r;
return DECLINED unless -e $r->filename; # should be $r->finfo
unless ($self->stream_ok) {
$r->log_reason('AllowStream forbidden');
return FORBIDDEN;
}
if ($self->check_stream_client and !$self->is_stream_client) {
my $useragent = $r->headers_in->{'User-Agent'};
$r->log_reason("CheckStreamClient is true and $useragent is not a streaming client");
return FORBIDDEN;
}
my $mime = $r->content_type;
my $file = $r->filename;
my $url = $r->uri;
my $info = $self->fetch_info($file,$mime);
return DECLINED unless $info; # not a legit mp3 file?
my $fh = $self->open_file($file) || return DECLINED;
binmode($fh); # to prevent DOS text-mode foolishness
my $size = -s $file;
my $bitrate = $info->{bitrate};
if ($self->can('bitrate') && $self->bitrate) {
($bitrate = $self->bitrate) =~ s/ kbps//i;
# quick approximation
$size = int($size * ($bitrate / $info->{bitrate}));
}
my $description = $info->{description};
my $genre = $info->{genre} || $self->lh->maketext('unknown');
my $range = 0;
$r->headers_in->{"Range"}
and $r->headers_in->{"Range"} =~ m/bytes=(\d+)/
and $range = $1
and seek($fh,$range,0);
# Look for a descriptive file that has the same base as the mp3 file.
# Also look for various index files.
my $icyurl = $self->stream_base(1);
my $base = basename($file);
$base =~ s/\.\w+$//; # get rid of suffix
my $dirbase = dirname($file);
my $urlbase = dirname($url);
foreach ("$base.html","$base.htm","index.html","index.htm") {
my $file = "$dirbase/$_";
if (-r $file) {
$icyurl .= "$urlbase/$_";
last;
}
}
$r->assbackwards(1);
$r->connection->keepalive(1);
$r->connection->keepalives($r->connection->keepalives+1);
$r->print("ICY ". ($range ? 206 : 200) ." OK$CRLF");
$r->print("icy-notice1: <BR>This stream requires a shoutcast/icecast compatible player.<BR>$CRLF");
$r->print("icy-notice2: Apache::MP3<BR>$CRLF");
$r->print("icy-name: $description$CRLF");
$r->print("icy-genre: $genre$CRLF");
$r->print("icy-url:$icyurl$CRLF");
$r->print("icy-pub:1$CRLF");
$r->print("icy-br:$bitrate$CRLF");
$r->print("Accept-Ranges: bytes$CRLF");
$r->print("Content-Range: bytes $range-" . ($size-1) . "/$size$CRLF")
if $range;
$r->print("Content-Length: $size$CRLF");
$r->print("Content-Type: $mime$CRLF");
$r->print("$CRLF");
return OK if $r->header_only;
if (my $timeout = $self->stream_timeout) {
my $seconds = $info->{seconds};
$seconds ||= 60; # shouldn't happen
my $fraction = $timeout/$seconds;
my $bytes = int($fraction * $size);
while ($bytes > 0) {
my $data;
my $b = read($fh,$data,2048) || last;
$bytes -= $b;
$r->print($data);
}
return OK;
} else {
my $data;
$r->print($data) while read($fh,$data,2048);
}
return OK;
}
# this generates a playlist for the MP3 player
sub send_playlist {
my $self = shift;
my ($urls,$shuffle) = @_;
return HTTP_NO_CONTENT unless $urls && @$urls;
my $r = $self->r;
my $base = $self->stream_base;
$r->content_type('audio/mpegurl');
return OK if $r->header_only;
# local user
my $local = $self->playlocal_ok && $self->is_local;
$self->shuffle($urls) if $shuffle;
$r->print("#EXTM3U$CRLF");
my $stream_parms = $self->stream_parms;
foreach (@$urls) {
$self->path_escape(\$_);
my $subr = $r->lookup_uri($_) or next;
my $file = $subr->filename;
my $type = $subr->content_type;
( run in 0.674 second using v1.01-cache-2.11-cpan-df04353d9ac )