aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Cro/BodyParser/VlcXML.rakumod38
-rw-r--r--lib/Lirc/Client.rakumod37
-rw-r--r--lib/Vlc/App.rakumod33
-rw-r--r--lib/Vlc/Client.rakumod46
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))})
+ }
+}