diff --git a/lib/Playlist/M3U.pm b/lib/Playlist/M3U.pm new file mode 100644 index 0000000..644c8ad --- /dev/null +++ b/lib/Playlist/M3U.pm @@ -0,0 +1,83 @@ +package Playlist::M3U; + +use strict; +use warnings; + +our $VERSION = 0.1; + +sub new { + my ($class) = @_; + + return bless({ items => [], attrs => {}, }, $class); +} + +sub items { + my ($self) = @_; + + return wantarray ? @{$self->{items}} : $self->{items}; +} + +sub load { + my ($self, $file) = @_; + + $self->{items} = []; + + open(my $FH, "<", $file) or return $!; + my @lines = <$FH>; + close($FH); + chomp for @lines; + + # safeguard + return "Not looks like playlist" + unless grep { $_ =~ m/^#EXTM3U/o } @lines; + + my $item = undef; + foreach my $line (@lines) { + # header + if ($line =~ m/#EXTM3U(\s+\S+?=\S+)*/oi) { + return "Multiple EXTM3U lines found" + if (scalar keys($self->{attrs})); + $self->{attrs} = $self->_parse_attrs($1); + } + # standart tags + if ($line =~ m/^\s*#EXTINF:(-?\d+(?:\.\d+)?)(\s+\S+?=\S+)*,(.*)/oi) { + $item //= { + duration => $1, + attrs => $self->_parse_attrs($2), + title => $3, + }; + } + # extended tags + if ($line =~ m/^\s*#EXT-X-\S+?:(\s*\S+?=\S+)/oi) { + # ignore + } + # comments + if ($line =~ m/^\s*#/) { + next; + } + # path / url + if ($line) { + $item->{file} = $line; + push @{$self->{items}}, $item; + undef $item; + } + } + + return $self->items; +} + +sub _parse_attrs { + my ($self, $str) = @_; + + return {} unless $str; + my %attrs = (); + $str =~ s/(^\s+|\s+$)//oi; + foreach my $token (split /\s+/, $str) { + my ($key, $value) = split("=", $token, 2); + $attrs{$key} = $value; + } + + return \%attrs; +} + +1;