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') {*}
my sub lirc_deinit(--> int32) is native('lirc_client') {*}
has Str $!socket;
has Bool $!verbose;
has int $!fd;
submethod BUILD(Str :$!socket=Str, Bool :$!verbose=False) {
$!fd = -1;
}
method !ensure-connected() {
if ($!fd < 0) {
$!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!) {
self!ensure-connected();
my $rc = lirc_send_one($!fd, $remote, $keysym);
if $rc != 0 {
lirc_deinit(); $!fd = -1;
X::Send.new().throw()
}
}
has Lock::Async $!orderer .= new;
method send(Str :$remote!, Str :$keysym!) {
$!orderer.lock.then({
LEAVE $!orderer.unlock;
self!send-sync(:$remote, :$keysym);
})
}
}