Browse Source

* extract xspf to separate package

master
Alex 'AdUser' Z 9 years ago
parent
commit
c3515d0dec
  1. 113
      lib/Text/Playlist/XSPF.pm
  2. 58
      t/xspf.t

113
lib/Text/Playlist/XSPF.pm

@ -1,113 +0,0 @@
package Text::Playlist::XSPF;
use strict;
use warnings;
use feature qw(switch);
use utf8;
use base 'Text::Playlist';
use XML::XPath;
our $VERSION = '0.02';
sub new {
my ($class) = @_;
return bless({ version => 0 }, $class);
}
sub parse {
my ($self, $text) = @_;
my @items = ();
my $xp = XML::XPath->new(xml => $text);
if (my $vers = $xp->find('/playlist/@version')) {
$self->{version} = $vers;
} else {
return "Can't find playlist version";
}
my $tracks = $xp->find('/playlist/trackList/track');
foreach my $track ($tracks->get_nodelist) {
my $item = {};
foreach my $child ($track->getChildNodes) {
next unless (ref $child eq 'XML::XPath::Node::Element');
my $value = $child->string_value();
given ($child->getName()) {
when (m/title/oi) { $item->{title} = $value; }
when (m/location/oi) { $item->{location} = $value; }
default { warn "garbage inside <track> element: $_ -> $value\n"; }
}
}
unless ($item->{title} and $item->{location}) {
warn "Missing mandatory 'title' or 'location' field\n";
next;
}
push @items, $item;
}
return wantarray ? @items : [ @items ];
}
sub dump { die("dump() unimplemented for XSPF format\n"); }
1;
__END__
=pod
=head1 NAME
Text::Playlist::XSPF - parser for 'xspf' format
=head1 SYNOPSIS
my $xspf = Text::Playlist::XSPF->new;
my @items = $xspf->load('/path/to/playlist.xspf');
foreach my $item (@items) {
<work with playlist items>
}
=head1 DESCRIPTION
Fast-and-dirty parser for xspf playlist.
Will be usefull if you're just want to read playlist or simple want
to convert such playlist to more common alternative.
=head2 C<load>
=head2 C<parse>
=head2 C<save>
=head2 C<dump>
For description of these methods see description in base class L<Text::Playlist>
=head1 Item format
Each parsed item has the following keys in hashref:
* location -- path or url, required. Following formats acceptable:
- Windows Path : file:///C:/music/foo.mp3
- Linux Path : file:///media/music/foo.mp3
- Relative Path : music/foo.mp3
- External URL : http://www.example.com/music/bar.ogg
* title -- title for given item, required
=head1 TODO
C<dump()> method still not implemented
=head1 SEE ALSO
L<XML::Toolkit> -- contains complete implementation for work with XSPF format
=head1 LINKS
L<https://en.wikipedia.org/wiki/XML_Shareable_Playlist_Format>
=head1 AUTHORS
Alex 'AdUser' Z <aduser@cpan.org>
=cut

58
t/xspf.t

@ -1,58 +0,0 @@
#!/usr/bin/perl
use strict;
use warnings;
use lib 'lib';
use POSIX qw(tmpnam);
use Test::More tests => 3;
require_ok('Text::Playlist::XSPF');
my $xspf = new_ok('Text::Playlist::XSPF' => []);
my $path = tmpnam();
open my $FH, ">", $path;
print $FH <<EOF;
<?xml version="1.0" encoding="UTF-8"?>
<playlist version="1" xmlns="http://xspf.org/ns/0/">
<trackList>
<track>
<title>Windows Path</title>
<location>file:///C:/music/foo.mp3</location>
</track>
<track>
<title>Linux Path</title>
<location>file:///media/music/foo.mp3</location>
</track>
<track>
<title>Relative Path</title>
<location>music/foo.mp3</location>
</track>
<track>
<title>External Example</title>
<location>http://www.example.com/music/bar.ogg</location>
</track>
</trackList>
</playlist>
EOF
close $FH;
my $out = [{
location => 'file:///C:/music/foo.mp3',
title => 'Windows Path',
}, {
title => 'Linux Path',
location => 'file:///media/music/foo.mp3',
}, {
title => 'Relative Path',
location => 'music/foo.mp3',
}, {
title => 'External Example',
location => 'http://www.example.com/music/bar.ogg',
}];
is_deeply(scalar $xspf->load($path), $out, "Loading test playlist");
unlink $path;
exit 0;
Loading…
Cancel
Save