Apache-MP3
view release on metacpan or search on metacpan
print $description;
print $CRLF;
} else {
$r->print('#EXTINF:' , $data->{seconds} ,
',', $data->{title},
' - ',$data->{artist},
' (',$data->{album},')',
$CRLF);
}
if ($local) {
$r->print($file,$CRLF);
} else {
$r->print ("$base$_?$stream_parms$CRLF");
}
}
return OK;
}
sub stream_parms {
my $self = shift;
return "stream=1";
}
# load the contents of a playlist (.m3u) from disk
sub load_playlist {
my $self = shift;
my $playlist = shift;
my @mp3s = ();
my $uri = dirname($self->r->uri);
local $_;
my $fh = IO::File->new($playlist)
or die "Failed to open $playlist";
while(<$fh>) {
chomp;
s/\#.*//; # get rid of comment and hint lines
s/\s+$//; # get rid of whitespace at end of lines
next unless $_;
push @mp3s, "$uri/$_";
}
$fh->close;
return @mp3s
}
# shuffle an array
sub shuffle {
my $self = shift;
my $list = shift;
for (my $i=0; $i<@$list; $i++) {
my $rand = rand(scalar @$list);
($list->[$i],$list->[$rand]) = ($list->[$rand],$list->[$i]); # swap
}
}
# top level for directory display
sub list_directory {
my $self = shift;
my $dir = shift;
return DECLINED unless -d $dir;
my $last_modified = (stat(_))[9];
$self->r->headers_out->add('ETag' => sprintf("%lx-%s", $last_modified, $VERSION));
if (my $check = $self->r->headers_in->{"If-None-Match"}) {
my ($time, $ver) = $check =~ /^([a-f0-9]+)-([0-9.]+)$/;
if ($check eq '*' or (hex($time) == $last_modified and $ver == $VERSION)) {
return HTTP_NOT_MODIFIED;
}
}
return DECLINED unless my ($directories,$mp3s,$playlists,$txtfiles)
= $self->read_directory($dir);
$self->r->content_type( $self->html_content_type );
return OK if $self->r->header_only;
$self->page_top($dir);
$self->directory_top($dir);
print "\n<!-- begin main -->\n";
if(@$directories) {
print "\n<!-- begin subdirs -->\n";
$self->list_subdirs($directories);
print "\n<!-- end subdirs -->\n";
}
if(@$txtfiles) {
print "\n<!-- begin txtfiles -->\n";
$self->list_txtfiles($txtfiles);
print "\n<!-- end txtfiles -->\n";
}
if(@$playlists) {
print "\n<!-- begin playlists -->\n";
$self->list_playlists($playlists);
print "\n<!-- end playlists -->\n";
}
if(%$mp3s) {
print "\n<!-- begin mp3s -->\n";
$self->list_mp3s($mp3s);
print "\n<!-- end mp3s -->\n";
}
print "\n<!-- end main -->\n";
print hr unless %$mp3s;
$self->directory_bottom($dir);
return OK;
}
# print the HTML at the top of the page
sub page_top {
my $self = shift;
my $dir = shift;
my $title = $self->r->uri;
print start_html(
-title => $title,
-head => meta({-http_equiv => 'Content-Type',
-content => 'text/html; charset='
. $self->html_content_type
my $cols = $self->subdir_columns;
my $rows = int(0.99 + @subdirs/$cols);
print start_table({-border=>0,-id=>'diroutertable'}),"\n";
if($self->subdir_columns == 1){
my $statsheader = '';
if($self->r->dir_config('CacheStats') && $self->r->dir_config('CacheDir')){
$statsheader = td(b('Last Accessed')). td(b('Times Accessed'));
}
print TR(
td(b('Directory')),
td(b('Play Options')),
td(b('Last Modified')),
$statsheader,
);
}
for (my $row=0; $row < $rows; $row++) {
print start_TR({-valign=>'BOTTOM',-align=>'LEFT'});
for (my $col=0; $col<$cols; $col++) {
my $i = $col * $rows + $row;
my $contents = $subdirs[$i] ? $self->format_subdir($subdirs[$i]) : ' ';
#only assume wrap in td() if multiple columns. should td() be moved to format_subdir() ?
print $self->subdir_columns == 1 ? $contents : td($contents);
}
print end_TR,"\n";
}
print end_table;
}
# given a list of CD directories, sort them
sub sort_subdirs {
my $self = shift;
my $subdirs = shift;
return sort @$subdirs; # alphabetic sort by default
}
# format a subdir entry and return its HTML
sub format_subdir {
my $self = shift;
my $subdir = shift;
my $subdirpath = $self->r->filename .'/'. $subdir;
# special handling if subdir is fully pathed
if (substr($subdir, -1) eq "/") {
chop $subdir;
$subdirpath = $self->r->lookup_uri($subdir)->filename;
}
my $nb = ' ';
(my $title = $subdir) =~ s/\s/$nb/og; # replace whitespace with
$title =~ s!^.*(/[^/]+/[^/]+)$!...$1!; # if dir is fully pathed, only keep 2 parts for title
my $uri = escape($subdir);
my $result;
my($atime,$mtime) = (stat($subdirpath))[8,9];
my($last,$times);
if($self->r->dir_config('CacheStats')){
($last,$times) = $self->stats($self->r->filename,$subdir);
}
if($self->subdir_columns == 1){
$result = td(
a({-href=>$uri.'/playlist.m3u?Play+All+Recursive=1'},
img({-src=>$self->cd_list_icon($subdir),
-align=>'ABSMIDDLE',
-class=>'subdir',
-alt=>$self->x('Stream'),
-border=>0})),
a({-href=>$uri.'/'},font({-class=>'subdirectory'},$title))
)
.td(
a({-class=>'subdirbuttons',
-href=>$uri.'/playlist.m3u?Shuffle+All+Recursive=1'},
'[' .
$self->x('Shuffle')
.']')
.$nb.
a({-class=>'subdirbuttons',
-href=>$uri.'/playlist.m3u?Play+All+Recursive=1'},
'['.
$self->x('Stream')
.']')."\n"
)
.td(
scalar(localtime($mtime))
);
if($self->r->dir_config('CacheStats')){
$result .= td($last) . td($times);
}
} else {
$result = start_table({-border=>0,-alight=>'LEFT'}).start_TR().td(
a({-href=>$uri.'/playlist.m3u?Play+All+Recursive=1'},
img({-src=>$self->cd_list_icon($subdir),
-align=>'LEFT',
-class=>'subdir',
-alt=>$self->x('Stream'),
-border=>0}))
).td({-valign => 'CENTER', -align => 'LEFT'},
a({-href=>$uri.'/'},font({-class=>'subdirectory'},$title)).
br."\n".
a({-class=>'subdirbuttons',
-href=>$uri.'/playlist.m3u?Shuffle+All+Recursive=1'},
'['.$self->x('Shuffle').']')
.$nb.
a({-class=>'subdirbuttons',
-href=>$uri.'/playlist.m3u?Play+All+Recursive=1'},
'['.$self->x('Stream').']')."\n"
).end_TR().end_table();
}
return $result;
}
( run in 2.871 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )