use v6.d; use Cro::HTTP::Client; use Cro::Uri::HTTP; use Cro::BodyParser::VlcXML; use XML; multi sub maybe-bool('true') { True } multi sub maybe-bool('false') { False } multi sub maybe-bool($x) { $x } sub xml-to-hash(XML::Element $elem) { if $elem.elements() -> @children { return %( @children.map: { .name => xml-to-hash($_) } ) } return maybe-bool($elem.contents().join('').trim) } class Vlc::Client { has Cro::HTTP::Client $!vlc; has Str $.password is required; has Str $.base-uri = 'http://127.0.0.1:8080/requests/'; has IO::Path() $.mrl-root = '/'; method !call-vlc(Str:D $path, *%args) { $!vlc ||= Cro::HTTP::Client.new( auth => { :username(), :password(self.password) }, add-body-parsers => [ Cro::BodyParser::VlcXML ], ); state Cro::Uri::HTTP $base-uri .= parse(self.base-uri); return $!vlc.get( $base-uri.add($path).add-query(|%args), ); } method command(Str:D $command, *%args) { return self!call-vlc('status.xml', :$command, |%args); } method play-file(Str:D :$path!, Str:D :$name!) { return self.command( 'in_play', input => self.mrl-root.child($path).child($name), ); } method status() { my $res = await self!call-vlc('status.xml'); my XML::Document $status = await $res.body; return Promise.kept(xml-to-hash($status.root)); } method playlist() { my $res = await self!call-vlc('playlist.xml'); my XML::Document $playlist = await $res.body; my @playlist-items = $playlist.elements() .grep(*.attribs eq 'Playlist').first .elements().map( -> $leaf { %( $leaf.attribs:p.Slip, current => $leaf.attribs:exists, ) }, ); return Promise.kept(@playlist-items); } }