diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Cro/BodyParser/VlcXML.rakumod | 38 | ||||
-rw-r--r-- | lib/Lirc/Client.rakumod | 37 | ||||
-rw-r--r-- | lib/Vlc/App.rakumod | 33 | ||||
-rw-r--r-- | lib/Vlc/Client.rakumod | 46 |
4 files changed, 154 insertions, 0 deletions
diff --git a/lib/Cro/BodyParser/VlcXML.rakumod b/lib/Cro/BodyParser/VlcXML.rakumod new file mode 100644 index 0000000..0750c9a --- /dev/null +++ b/lib/Cro/BodyParser/VlcXML.rakumod @@ -0,0 +1,38 @@ +use v6.d; +use Cro::BodyParser; +use Cro::HTTP::Message; +use XML; + +class Cro::BodyParser::VlcXML does Cro::BodyParser { + method is-applicable(Cro::HTTP::Message $message --> Bool) { + with $message.content-type { + .type eq 'application'|'text' && .subtype eq 'xml' || .suffix eq 'json' + } + else { + False + } + } + + method parse(Cro::HTTP::Message $message --> Promise) { + Promise( + supply { + my $payload = Blob.new; + + whenever $message.body-byte-stream -> $blob { + $payload ~= $blob; + LAST emit from-xml($payload.decode('utf-8')); + } + + # if we had LibXML + + # my LibXML::PushParser $parser .= new(); + # + # whenever $message.body-byte-stream -> $blob { + # $parser.push($blob); + # $payload ~= $blob; + # LAST emit $parser.finish-push; + # } + } + ) + } +} diff --git a/lib/Lirc/Client.rakumod b/lib/Lirc/Client.rakumod new file mode 100644 index 0000000..0065335 --- /dev/null +++ b/lib/Lirc/Client.rakumod @@ -0,0 +1,37 @@ +use v6.d; +use NativeCall; + +class Lirc::Client { + our class X::Init is Exception { + has Int $.rc; + method message { "Failed to init LIRC client: $!rc" } + } + + our class X::Send is Exception { + method message { "Failed to send command to LIRC client" } + } + + my sub lirc_get_local_socket(Str $socket is encoded('utf8'), int32 $verbose --> int32) is native('lirc_client') {*} + my sub lirc_send_one(int32 $fd, Str $remote is encoded('utf8'), Str $keysym is encoded('utf8') --> int32) is native('lirc_client') {*} + + has int $!fd; + + submethod BUILD(Str :$socket=Str, Bool :$verbose=False) { + $!fd = lirc_get_local_socket($socket, $verbose ?? 1 !! 0); + X::Init.new(rc => -$!fd).throw() if $!fd < 0; + } + + method !send-sync(Str :$remote, Str :$keysym) { + my $rc = lirc_send_one($!fd, $remote, $keysym); + X::Send.new().throw() if $rc != 0; + } + + # copied from OO::Actors + has Lock::Async $!orderer .= new; + method send(Str :$remote, Str :$keysym) { + $!orderer.lock.then({ + LEAVE $!orderer.unlock; + self!send-sync(:$remote, :$keysym); + }) + } +} diff --git a/lib/Vlc/App.rakumod b/lib/Vlc/App.rakumod new file mode 100644 index 0000000..e4401e6 --- /dev/null +++ b/lib/Vlc/App.rakumod @@ -0,0 +1,33 @@ +use v6.d; +use Cro::HTTP::Server; +use Cro::HTTP::Router; +use Vlc::Client; + +class Vlc::App { + has Vlc::Client $.vlc is required; + has Int $.port = 8080; + has Cro::Service $!service handles <stop>; + + method start() { + my $application = route { + resources-from %?RESOURCES; + + get -> { resource 'vlc.html' } + + post -> 'play' { await self.vlc.command('pl_play') } + post -> 'pause' { await self.vlc.command('pl_pause') } + post -> 'stop' { await self.vlc.command('pl_stop') } + + get -> 'status' { + my $status = await self.vlc.status(); + content 'application/json', $status; + } + }; + + $!service = Cro::HTTP::Server.new( + :port(self.port), :$application, + ); + + return $!service.start(); + } +} diff --git a/lib/Vlc/Client.rakumod b/lib/Vlc/Client.rakumod new file mode 100644 index 0000000..3620d47 --- /dev/null +++ b/lib/Vlc/Client.rakumod @@ -0,0 +1,46 @@ +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/'; + + method !call-vlc(Str $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 $command, *%args) { + return self!call-vlc('status.xml', :$command, |%args); + } + + method status() { + my $res = await self!call-vlc('status.xml'); + my XML::Document $status = await $res.body; + return Promise.kept({:status(xml-to-hash($status.root))}) + } +} |