RCU - Remote Control Unit Interface


RCU documentation Contained in the RCU distribution.

Index


Code Index:

NAME

Top

RCU - Remote Control Unit Interface

SYNOPSIS

Top

   use RCU;

DESCRIPTION

Top

This module provides a generic interface to remote control units (only receivers at the moment, as I cannot test more). It only provides an abstract management interface, other modules are required for the hardware access (RCU::Irman and RCU::Lirc are included, however).

GETTING STARTED

Please read RCU::Receipts to get some idea on how to proceed after you installed the module (testing & standard techniques).

THE RCU CLASS

Top

The RCU class provides a general interface to anything you might want to do to, it represents your application.

$rcu = new RCU "interface-spec"

Creates a new RCU application. interface must be an interface specification similar to DBI's DSN:

 RCU:ifname:arg:arg...

Examples: low-level interface (without RCU:: prefix) or an arrayref containing name and constructor arguments. If the interface name has a :: prefix it will be used as-is (without that prefix, of course).

For a much better interface, see RCU::Event.

$rcu->interface

Return the RCU::Interface object used by this RCU object.

($keycode, $repeat) = $rcu->get
($keycode, $repeat) = $rcu->poll

Simplified interface to the RCU (See also RCU::Event), return a cooked keycode and a repeat count (initial keypress = 0, increasing while the key is pressed). If get is called in scalar context it only returns unrepeated keycodes.

This interface is problematic: no key-up events are generated, and the repeat events occur pseudo-randomly and have no time relation between each other, so better use the event-based interface provided by RCU::Event.

THE RCU::Key CLASS

Top

This class collects information about rcu keys.

THE RCU::Interface CLASS

Top

RCU::Interface provides the base class for all rcu interfaces, it is rarely used directly.

fd

Return a unix filehandle that can be polled, or -1 if this is not possible.

($time, $raw, $cooked) = $if->get
($time, $raw, $cooked) = $if->poll

Wait until a RCU event happens and return it. If the device can translate raw keys events (e.g. hex key codes) into meaningful names ("cooked" keys) it will return the cooked name as second value, otherwise both return values are identical.

get always returns an event, waiting if neccessary, while poll only checks for an event: If one is pending it is returned, otherwise poll returns nothing.

SEE ALSO

Top

RCU::Irman, RCU::Lirc.

AUTHOR

Top

This perl extension was written by Marc Lehmann <schmorp@schmorp.de>.

BUGS

Top

No send interface.


RCU documentation Contained in the RCU distribution.
package RCU;

$VERSION = 0.021;

use Carp;

sub new {
   my $class = shift;
   my $if = shift;
   my $self = bless {}, $class;

   my ($rcu, $ifname, @ifargs) = split /:/, $if;
   $rcu eq "RCU" or croak "unknown interface name syntax";
   $ifname = "RCU::$ifname";
   do { eval "require $ifname"; die $@ if $@ } unless exists ${"$ifname\::"}{VERSION}; # best bet
   $self->{if} = $ifname->new(@ifargs);

   $self;
}

sub interface {
   $_[0]->{if};
}

$some_key;
$last_key;
$next_time;
$last_repeat;

sub _poll {
   my $self = shift;
   my @code = @_;
   return unless @code;
   my $now = shift @code;
   my $key = $RCU::Key::db{$code[0]}
             || ($RCU::Key::db{$code[1]} ||= new RCU::Key
                   $some_key->[0] || $RCU::Key::db{""}{"<default>"}[0] || {},
                   $code[1]);

   my $repeat_min  = $key->[0]{repeat_min} || 1;
   my $repeat_freq = $key->[0]{repeat_freq} || 0.2;
   if ($last_key == $key) {
      if ($now <= $next_time) {
         $last_repeat++;
      } else {
         $last_repeat = 0;
      }
   } else {
      $last_repeat = 0;
   }
   $some_key = $last_key = $key;
   $next_time = $now + $repeat_freq;
   if ($last_repeat && $last_repeat < $repeat_min) {
      return;
   } else {
      my $repeat = $last_repeat >= $repeat_min ? $last_repeat - $repeat_min + 1 : 0;
      return ($key->[2] || $key->[1], $repeat);
   }
}

sub poll {
   my $self = shift;
   $self->_poll($self->{if}->poll);
}

sub get {
   my $self = shift;
   while() {
     my @code = $self->_poll($self->{if}->get);
     if (@code) {
        return @code if wantarray;
        return $code[0] unless $code[0];
     }
   }
}


package RCU::Key;

sub new {
   my $class = shift;
   my ($def, $cooked) = @_;
   bless [$def, $cooked], $class;
}

# RCU key database management

%db;

# $rcu{rcu_name}->{raw|cooked}->key;

# $def, $cooked

sub add_key {
   my ($def, $raw, $cooked) = @_;
   return $db{$def->{rcu_name}}{$raw} = new RCU::Key $def, $cooked;
}

package RCU::Config::Parser;

my $def;
my @def;

sub def(&) {
   my $sub = shift;
   push @def, $def;
   $def = $def ? {%$def} : {};
   &$sub;
}

sub rcu_name($) {
   $def->{rcu_name}    = shift;
}

sub repeat_freq($) {
   $def->{repeat_freq} = shift;
}

sub repeat_min($) {
   $def->{repeat_min}  = shift;
}

sub key($;$) {
   my ($raw, $cooked) = @_;
   RCU::Key::add_key($def, $raw, $cooked || $raw);
}

package RCU::Interface;

use Carp;

sub new {
   my $class = shift;
   my $self = bless {}, $class;
   $self;
}

# do get emulation for interfaces that don't have get. slow but who cares, anyway

sub get {
   my $self = shift;
   my $fd = $self->fd;
   $fd >= 0 or croak ref($self)."::get cannot be emulated without an fd method";
   my @code;
   while (!(@code = $self->poll)) {
      my $in = ""; vec ($in, $fd, 1) = 1;
      select $in, undef, undef, undef;
   }
   wantarray ? @code : $code[1];
}

1;