IR(2)                                                       IR(2)

     NAME
          ir - infrared remote control module

     SYNOPSIS
          include     "ir.m";

          ir    := load Ir Ir->PATH; # for real remotes
          simir := load Ir Ir->SIMPATH; # for keyboard simulator

          init:       fn(irc: chan of int, pidc: chan of int): int;
          translate:  fn(key: int): int;

     DESCRIPTION
          Programs running with the Prefab toolkit (see prefab-
          intro(2)) are controlled by an infrared remote control
          device.  If such a device is not present, the system may
          simulate it from the keyboard by loading the module in file
          Ir->SIMPATH.  Although originally designed for use with Pre-
          fab, these modules are general enough to be used directly by
          non-Prefab applications.

          The Ir module defines codes for representing the remote con-
          trol keys.  Whether the remote is real or simulated, the
          init function does the appropriate actions to initialize the
          device, and then spawns a process to return the codes on the
          irc channel.  The process ID of that process is sent on the
          channel pidc when the process starts; init's caller must
          receive it.  It can be used to kill the controlling process
          when the application finishes.

          The codes are:

          Ir->ChanUP, Ir->ChanDN
               The Channel-Up and Channel-Down buttons.  The keyboard
               equivalents are r and c.

          Ir->Enter
               The Enter button.  The keyboard equivalent is the SPACE
               bar.

          Ir->EOF
               An end of file from the remote device.  After sending
               one, no more codes will be sent on irc.

          Ir->Error
               An unknown or invalid input from the remote device.

          Ir->FF, Ir->Rew
               The Fast-Forward and Rewind buttons.  The keyboard
               equivalents are k and j.

     Page 1                       Plan 9             (printed 3/28/24)

     IR(2)                                                       IR(2)

          Ir->Mute
               The Mute button.  There is no keyboard equivalent.

          Ir->Power
               The Power button.  The keyboard equivalent is the
               Delete key.

          Ir->Rcl
               The Recall button.  The keyboard equivalent is x.

          Ir->Record
               The Record button.  There is no keyboard equivalent.

          Ir->Select
               The Select button.  The keyboard equivalent is the
               Return or Enter key.

          Ir->Up, Ir->Dn
               The Up and Down buttons.  The keyboard equivalents are
               i and m.

          Ir->VolUP, Ir->VolDN
               The Volume-Up and Volume-Down buttons.  The keyboard
               equivalents are t and v.

          Ir->Zero, Ir->One, Ir->Two, etc.
               The digit buttons, 0 through 9.  The keyboard equiva-
               lents are the corresponding numeral keys.

          The translate function converts the device's raw codes into
          the constants defined by the module.  For example, with the
          simulated remote control, translate('3') returns Ir->Three.
          Translate is only necessary for programs that wish to manage
          their own simulation of the remote.

          Programs that  drive the remote control directly, must load
          the appropriate Ir implementation module and initialise it.
          The following example uses the absence of a simulator module
          to infer that a real remote control is available.

          implement Irtest;

          include "sys.m";
          include "draw.m";
          include "ir.m";

          Irtest: module
          {
             init:  fn(ctxt: ref Draw->Context, argv: list of string);
          };

          init(nil: ref Draw->Context, nil: list of string)

     Page 2                       Plan 9             (printed 3/28/24)

     IR(2)                                                       IR(2)

          {
              sys := load Sys Sys->PATH;

              # First try the keyboard Ir simulator.
              # If that is not present, use Ir directly.

              ir := load Ir Ir->SIMPATH;
              if(ir == nil)
                  ir = load Ir Ir->PATH;
              if(ir == nil){
                  sys->print("Ir module not loaded: %r\n");
                  return;
              }
              irc := chan of int;
              pidc := chan of int;
              if(ir->init(irc, pidc) < 0){
                  sys->print("Can't initialize Ir device: %r\n");
                  return;
              }
              pid := <-pidc;
              while((irraw := <-irc) != Ir->EOF) {
                  irval := ir->translate(irraw);
                  if(irval == Ir->Power)
                      break;
                  sys->print("command %d -> %d\n", irraw, irval);
              }
              kill(pid);
          }

          Mux(1) provides one model for the use of an infrared remote
          control to control a group of applications.  Init is invoked
          once by mux, and the codes then multiplexed between its
          applications as follows.  Mux creates a graphics context for
          each application (see draw-context(2)). This context
          includes channels to the mux program and to the Ir device:
          Draw->Context.ctomux and Draw->Context.cinput.  Applications
          do not see the Ir->Rcl command.  Instead, mux program inter-
          cepts it and reactivates its own menu.  The following exam-
          ple establishes communication with mux and then reads Ir
          commands until it see Ir->Enter.

          implement Command;

          include "sys.m";
          include "draw.m";
          include "ir.m";

          Command: module
          {
            init: fn(ref Draw->Context; list of string);
          };

     Page 3                       Plan 9             (printed 3/28/24)

     IR(2)                                                       IR(2)

          init(ctxt: ref Draw->Context; argv: list of string)
          {
            sys := load Sys Sys->PATH;

            # Tell mux to start sending input.
            ctxt.ctomux <-= Draw->AMstartinput;
            for(;;) {
              key := <-ctxt.cinput;
              sys->print("command %d\n", key);
              if(key == Ir->Enter)
                break;
            }

            #  Tell mux this thread is going away.
            ctxt.ctomux <-= Draw->AMexit;
          }

     SOURCE
          /appl/lib/ir.b
          /appl/lib/irmpath.b
          /appl/lib/irsim.b

     SEE ALSO
          limbo(1), mux(1), intro(2), draw-intro(2), prefab-intro(2)

     Page 4                       Plan 9             (printed 3/28/24)