Difference between revisions of "LircChannelChanger"

From MythTV Official Wiki
Jump to: navigation, search
Line 785: Line 785:
 
<pre>
 
<pre>
 
#
 
#
# Configuration file for the ChannelChange script
+
# Configuration file for the LircChannelChanger script
 
#
 
#
 
# Except for the configfile option, all other options
 
# Except for the configfile option, all other options

Revision as of 05:51, 29 November 2011


Author Gary Buhrmaster
Description Lirc Channel Change script with extensive configuration options
Supports



This is a script that performs channel changing via lirc.

This script is designed to provide flexible configuration options to support many (perhaps most) of the requirements of a channel changing script that uses lirc.


Script.png LircChannelChanger

#!/usr/bin/perl

#
# LircChannelChanger
#

#
# Copyright (c) 2009-2011 Gary Buhrmaster <gary.buhrmaster@gmail.com>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
#  * Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
#
#  * Redistributions in binary form must reproduce the above
#    copyright notice, this list of conditions and the following
#    disclaimer in the documentation and/or other materials
#    provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS 'AS IS' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#

#
# Channel Changing script for mythtv and lirc
#
# There are a lot of channel changing scripts for mythtv and lirc,
# this one differs in its ability to support more flexible options
# from the command line, allowing one script to do the work of many.
# It also supports locking, to insure that only one channel changer
# is being run at once (this is important with multiple tuners and
# with multiple programs independently running/changing channels
# since irsend "SET_TRANSMITTERS" is global).
# 

#
# Our perl dependencies
#
use strict;
use Fcntl qw(:DEFAULT :flock);
use IPC::SysV qw(SEM_UNDO IPC_PRIVATE IPC_NOWAIT S_IRUSR S_IWUSR IPC_CREAT);
use IPC::Semaphore;
use Getopt::Long qw(GetOptions GetOptionsFromString);
use Time::HiRes qw (sleep);
use FindBin qw($Bin $Script);

#
# lockType can be either semaphore or file or none.
# semaphore only tested for linux (which has
# semaphore cleanup protections).  None is not
# recommended (since running multiple apps using
# lirc is going to eventually cause confusion).
#
my $lockType      = 'semaphore';

my $lockFile      = '/tmp/LircChannelChanger.lockfile';
my $lockFH;
my $lockSemKey    = 727522346;       # "Random" value for key
my $lockSem;

my @transmitters;                    # Transmitters to send on
my $key;                             # General key variable
my @FREQID;                          # The (possibly transformed) freqid string
my $prevkey       = '';              # Previously issued key
my $device;                          # lirc --device value
my $address;                         # lirc --address value
my $delay;                           # Delay after keys (for all)
my $tdelay;                          # Delay after set_transmitters
my $bdelay;                          # Delay after before keys
my $adelay;                          # Delay after after keys
my $ddelay;                          # Delay after digit keys
my $rdelay        = 0;               # Delay between repeated keys
my $idelay        = 0;               # Delay after initialization (after lock)
my $edelay        = 0;               # Delay before exit (before lock release)
my $delayaccum    = 0;               # Delay accumulated
my $before;                          # Keys to send before channel
my $after;                           # Keys to send after channel
my $digitprefix;                     # Digit Keyname prefix (sometimes key_)
my $digitnames;                      # Use digit names (i.e. 1 -> One)
my $options       = '';              # Constructed options
my $debug         = 0;               # Debug messages
my $remote;                          # Remote name
my $channeldigits;                   # Number of channel digits
my $channeltransform;                # Channel number transform routine
my $help          = 0;               # Help?
my $irsend        = 'irsend';        # Lirc irsend program

my %digitname;
   $digitname{0}  = 'Zero'; 
   $digitname{1}  = 'One';
   $digitname{2}  = 'Two';
   $digitname{3}  = 'Three';
   $digitname{4}  = 'Four';
   $digitname{5}  = 'Five';
   $digitname{6}  = 'Six';
   $digitname{7}  = 'Seven';
   $digitname{8}  = 'Eight';
   $digitname{9}  = 'Nine';

#
# Use GetOptions to process the command line options
#
if (!GetOptions ( "device=s"                 => \$device,
                  "address=s"                => \$address,
                  "delay=f"                  => \$delay,
                  "tdelay=f"                 => \$tdelay,
                  "bdelay=f"                 => \$bdelay,
                  "adelay=f"                 => \$adelay,
                  "ddelay=f"                 => \$ddelay,
                  "rdelay=f"                 => \$rdelay,
                  "idelay=f"                 => \$idelay,
                  "edelay=f"                 => \$edelay,
                  "xmitters|transmitters=i"  => \@transmitters,
                  "beforekeys=s"             => \$before,
                  "afterkeys=s"              => \$after,
                  "digitprefix=s"            => \$digitprefix,
                  "digitnames!"              => \$digitnames,
                  "channeldigits=i"          => \$channeldigits,
                  "channeltransform=s"       => \$channeltransform,
                  "remote=s"                 => \$remote,
                  "cf|configfilename=s"      => sub { processConfig(@_[1]) },
                  "locktype=s"               => \$lockType,
                  "lockfilename=s"           => \$lockFile,
		  "lockkey=i"                => \$lockSemKey,
                  "irsend=s"                 => \$irsend,
		  "help!"                    => \$help,
                  "debug!"                   => \$debug))
  {
    exit 1;
  }

#
# print out script usage for "help" argument or incorrect usage of command
#
if ($help)
  {
    my $usage = <<ECHO;

$Script:
    Script to perform channel changing for mythtv using lirc

    Usage: $Script <options> nnn

    Options:
            --help                          Print help
            --debug                         Print additional debugging info
            --configfilename=               Read configuration options from file
                                            (alt name is cf) default is none.
                                            *usually* the configfilename option
                                            should be specified first (so that
                                            one can override any specifications).
            --remote=                       Remote name for irsend (Reqd)
            --transmitter=                  Transmitter to set (multiple allowed).
                                            default is none specified.
            --beforekeys=                   Keys to send before channel numbers.
                                            specified as a string of keys ("exit exit")
                                            default is none.
            --afterkeys=                    Keys to send after channel numbers.
                                            specified as a string of keys ("enter enter")
                                            default is none.
            --delay=                        Delay after key sends (can be fractional).
                                            Global setting.  default is no delay.
            --tdelay=                       Delay after set_transmitter (can be fractional).
                                            default is delay value.
            --bdelay=                       Delay after each before key (can be fractional).
                                            default is delay value.
            --adelay=                       Delay after each after key (can be fractional).
                                            default is delay value.
            --ddelay=                       Delay after each digit key (can be fractional).
                                            default is delay value.
            --rdelay=                       Delay between repeated keys (can be fractional)
                                            if needed by receiver to discriminate between
                                            two identical key presses (compensate for receiver
                                            bounce compensation detection).
                                            default is 0.
            --idelay=                       Delay after initialization (and acquiring lock)
            --edelay=                       Delay before exit (and releasing lock)
            --device=                       --device=<s> for irsend.
                                            default is irsend default.
            --address=                      --address=<s> for irsend.
                                            default is irsend default.
            --channeldigits=                Some STBs will change the channel
                                            faster if the exact number of
                                            digits are sent with leading 0s.
                                            default is none.
            --channeltransform=             Channel digit transform routine.
                                            Mythtv allows one to send a string
                                            for the channel number.  This
                                            routine would transform the string
                                            into keys for irsend.
            --digitprefix=                  Some remotes have now renamed and
                                            prefixed the channel key names with
                                            (usually) KEY_.  Specify
                                            --digitprefix=KEY_ for
                                            those.  NOTE: This *only* applies
                                            to the channel digits (i.e.
                                            '0' is changed to 'key_0').
                                            default is no prefix.
            --digitnames                    Convert digits to names (i.e. 1 -> One).
                                            default is no.
            --locktype=                     'none', 'file', or 'semaphore' (the default)
                                            specifies the type of locking to perform.
            --lockfile=                     The lockfile name for locktype 'file'.
                                            default '/tmp/ChannelChanger.lockfile'.
            --lockkey=                      The semaphore number for locktype 'semaphore'.
                                            default 727522346 ("arbitrary" value).
            --irsend=                       The lirc irsend executable binary.
                                            default is 'irsend' which will search PATH

       Note that option names can be abbreviated to the shortest unique name,
       so, for example locktype can be shortened to lockt, since that is the
       shortest unique value.

ECHO
    print $usage;
    exit 1;     
  }

#
# Do some option validation
#

#
# The one mandatory option is "remote"
#
if ((!defined($remote)) || ("$remote" eq ''))
  {
    print "A remote name must be specified\n";
    exit 1;
  }

#
# Do some sanity checking of any other options specified
#
if (defined($delay) && ($delay < 0))
  {
    print "The delay value must be positive\n";
    exit 1;
  }
if (defined($tdelay) && ($tdelay < 0))
  {
    print "The tdelay value must be positive\n";
    exit 1;
  }
if (defined($bdelay) && ($bdelay < 0))
  {
    print "The bdelay value must be positive\n";
    exit 1;
  }
if (defined($adelay) && ($adelay < 0))
  {
    print "The adelay value must be positive\n";
    exit 1;
  }
if (defined($ddelay) && ($ddelay < 0))
  {
    print "The ddelay value must be positive\n";
    exit 1;
  }
if (defined($rdelay) && ($rdelay < 0))
  {
    print "The rdelay value must be positive\n";
    exit 1;
  }
if (defined($idelay) && ($idelay < 0))
  {
    print "The idelay value must be positive\n";
    exit 1;
  }
if (defined($edelay) && ($edelay < 0))
  {
    print "The edelay value must be positive\n";
    exit 1;
  }
if (defined($channeldigits) && (($channeldigits < 0) || ($channeldigits > 10)))
  {
    print "The channeldigits value must be positive and no greater than 10\n";
    exit 1;
  }
if (scalar(@transmitters) > 0)
  {
    foreach (@transmitters)
      {
        if (("$_" !~ /^\d+$/) || ($_ < 1) || ($_ > 32))
          {
            print "The transmitter value must be an integer between 1 and 32 (inclusive)\n";
            exit 1;
          }
      }
  }
if (("$lockType" ne 'none') && ("$lockType" ne 'semaphore') && ("$lockType" ne 'file'))
  {
    print "The locktype must be none, file, or semaphore\n";
    exit 1;
  }
if (defined($lockSemKey) && ($lockSemKey < 0))
  {
    print "The lockkey value must be positive\n";
    exit 1;
  }
if (defined($channeltransform))
  {
    if (! -e "$channeltransform")
      {
        print "The channeltransform program was not found (not in PATH?) \n";
        exit 1;
      }
    if (! -x "$channeltransform")
      {
        print "The channeltransform program must be executable\n";
        exit 1;
      }
  }

#
# Make sure debugging output makes it out
#
if ($debug)
  {
    select(STDERR); $| = 1;             # make unbuffered
    select(STDOUT); $| = 1;             # make unbuffered
  }

#
# Simplify delay checks later
#
$delay = 0 if (!defined($delay));
$tdelay = $delay if (!defined($tdelay));
$bdelay = $delay if (!defined($bdelay));
$adelay = $delay if (!defined($adelay));
$ddelay = $delay if (!defined($ddelay));

#
# Build up irsend options string
#
$options .= " --address=$address" if (defined($address) && ("$address" ne ''));
$options .= " --device=$device" if (defined($device) && ("$device" ne ''));

#
# Try to prevent multiple processes using the IR transciever
#
if (!lockGet())
  {
    print "Unable to aquire lock on $lockFile\n";
    exit 1;
  }

#
# If requested, sleep at initialization
#
if ($idelay != 0)
  {
    print STDERR "sleeping $idelay after lockGet and before lirc operations\n" if($debug);
    sleep($idelay);
  }

#
# If transmitters specified, set them
#
if (scalar(@transmitters) > 0)
  {
    my $emitters = join(' ', @transmitters);
    print STDERR "Issuing $irsend $options SET_TRANSMITTERS $emitters\n" if ($debug);
    system "$irsend $options SET_TRANSMITTERS $emitters";
    if ($? == 0)
      {
        print STDERR "$irsend child exited with value $?\n" if ($debug);
      }
    elsif ($? == -1) 
      {
        print STDERR "failed to execute $irsend: $!\n";
      }
    elsif ($? & 127) 
      {
        printf STDERR "$irsend child died with signal %d, %s coredump\n",
            ($? & 127),  ($? & 128) ? 'with' : 'without';
      }
    else
      {
        printf STDERR "$irsend child exited with value %d\n", $? >> 8;
      }
    if ($tdelay != 0)
      {
        print STDERR "adding $tdelay to delay accumulator after set_transmitters\n" if ($debug);
        $delayaccum += $tdelay
      }
  }

#
# Send the before keys, if any specified
#
if (defined($before) && ("$before" ne ''))
  {
    foreach $key (split(/ /,$before))
      {
        if (($rdelay != 0) && ("$key" eq "$prevkey"))
          {
            print STDERR "adding $rdelay to delay accumulator due to repeated key\n" if ($debug);
            $delayaccum += $rdelay;
          }
        if ($delayaccum != 0)
          {
            print STDERR "sleeping for the accumulated delay $delayaccum\n" if($debug);
            sleep ($delayaccum);
            $delayaccum = 0;
          }
        print STDERR "Issuing $irsend $options SEND_ONCE $remote $key\n" if($debug);
        system "$irsend $options SEND_ONCE $remote $key";
        if ($? == 0) 
          {
            print STDERR "$irsend child exited with value $?\n" if ($debug);
          }
        elsif ($? == -1) 
          {
            print STDERR "failed to execute $irsend: $!\n";
          }
        elsif ($? & 127) 
          {
            printf STDERR "$irsend child died with signal %d, %s coredump\n",
                ($? & 127),  ($? & 128) ? 'with' : 'without';
          }
        else 
          {
            printf STDERR "$irsend child exited with value %d\n", $? >> 8;
          }
        $prevkey = "$key";
        if ($bdelay != 0)
          {
            print STDERR "adding $bdelay to delay accumulator after before key\n" if($debug);	
            $delayaccum += $bdelay;
          }
      }
  }

#
# What remains is the channel number,
# although technically it is the "freqid"
# column, which may need to be transformed
# by an external script (if channeltransform
# is specified).  While not normally required,
# we support the capability for those special
# cases (and there are always special cases).
#
@FREQID = @ARGV;
if (defined($channeltransform))
  {
    my $a = join(' ', @FREQID);
    my $t = `$channeltransform $a`;
    chomp($t);
    print STDERR "transformed freqid $a into $t\n" if($debug);
    @FREQID = split(/ /,"$t");
  }

#
# What remains should be the channel number
# If the "token" appears to be an integer,
# we will treat it as a channel number,
# otherwise, just send along the key(s)
#
foreach $key (@FREQID)
  {
    if ($key =~ /^\d+$/)
      {
        my $digit;
        if (defined($channeldigits) && (($channeldigits > 0) && ($channeldigits > length($key))))
          {
            $key = substr('0000000000' . $key, (-$channeldigits));
          }
        foreach $digit (split(//,$key))
          {
            if (defined($digitnames) && ($digitnames))
              {
                if (defined($digitname{$digit}))
                  {
                    $digit = $digitname{$digit};
                  }
              }
            $digit = "$digitprefix" . $digit if (defined($digitprefix));
            if (($rdelay != 0) && ("$digit" eq "$prevkey"))
              {
                print STDERR "adding $rdelay to delay accumulator due to repeated key\n" if ($debug);
                $delayaccum += $rdelay;
              }
            if ($delayaccum != 0)
              {
                print STDERR "sleeping for the accumulated delay $delayaccum\n" if($debug);
                sleep ($delayaccum);
                $delayaccum = 0;
              }
            print STDERR "Issuing $irsend $options SEND_ONCE $remote $digit\n" if ($debug);
            system "$irsend $options SEND_ONCE $remote $digit";
            if ($? == 0)
              {
                print STDERR "$irsend child exited with value $?\n" if ($debug);
              }
            elsif ($? == -1)
              {
                print STDERR "failed to execute $irsend: $!\n";
              }
            elsif ($? & 127)
              {
                printf STDERR "$irsend child died with signal %d, %s coredump\n",
                    ($? & 127),  ($? & 128) ? 'with' : 'without';
              }
            else
              {
                printf STDERR "$irsend child exited with value %d\n", $? >> 8;
              }
            $prevkey = "$digit";
            if ($ddelay != 0)
              {
                print STDERR "adding $ddelay to delay accumulator after digit key\n" if($debug);
                $delayaccum += $ddelay;
              }
          }
      }
    else
      {
        if (($rdelay != 0) && ("$key" eq "$prevkey"))
          {
            print STDERR "adding $rdelay to delay accumulator due to repeated key\n" if ($debug);
            $delayaccum += $rdelay;
          }
        if ($delayaccum != 0)
          {
            print STDERR "sleeping for the accumulated delay $delayaccum\n" if($debug);
            sleep ($delayaccum);
            $delayaccum = 0;
          }
        print STDERR "Issuing $irsend $options SEND_ONCE $remote $key\n" if($debug);
        system "$irsend $options SEND_ONCE $remote $key";
        if ($? == 0)
          {
            print STDERR "$irsend child exited with value $?\n" if ($debug);
          }
        elsif ($? == -1)
          {
            print STDERR "failed to execute $irsend: $!\n";
          }
        elsif ($? & 127)
          {
            printf STDERR "$irsend child died with signal %d, %s coredump\n",
                ($? & 127),  ($? & 128) ? 'with' : 'without';
          }
        else
          {
            printf STDERR "$irsend child exited with value %d\n", $? >> 8;
          }
        $prevkey = "$key";
        if ($ddelay != 0)
          {
            print STDERR "adding $ddelay to delay accumulator after digit key\n" if($debug);
            $delayaccum += $ddelay;
          }
      }
  }

#
# Send the after keys, if any specified
#
if (defined($after) && ("$after" ne ''))
  {
    foreach $key (split(/ /,$after))
      {
        if (($rdelay != 0) && ("$key" eq "$prevkey"))
          {
            print STDERR "adding $rdelay to delay accumulator due to repeated key\n" if ($debug);
            $delayaccum += $rdelay;
          }
        if ($delayaccum != 0)
          {
            print STDERR "sleeping for the accumulated delay $delayaccum\n" if($debug);
            sleep ($delayaccum);
            $delayaccum = 0;
          }
        print STDERR "Issuing $irsend $options SEND_ONCE $remote $key\n" if($debug);
        system "$irsend $options SEND_ONCE $remote $key";
        if ($? == 0)
          {
            print STDERR "$irsend child exited with value $?\n" if ($debug);
          }
        elsif ($? == -1)
          {
            print STDERR "failed to execute $irsend: $!\n";
          }
        elsif ($? & 127)
          {
            printf STDERR "$irsend child died with signal %d, %s coredump\n",
                ($? & 127),  ($? & 128) ? 'with' : 'without';
          }
        else
          {
            printf STDERR "$irsend child exited with value %d\n", $? >> 8;
          }
        $prevkey = "$key";
        if ($adelay != 0)
          {
            print STDERR "adding $adelay to delay accumulator after after key\n" if($debug);
            $delayaccum += $adelay;
          }
      }
  }

#
# If requested, sleep before exiting
#
if ($edelay != 0)
  {
    print STDERR "sleeping $edelay before lockFree and exit\n" if($debug);
    sleep($edelay);
  }

#
# IR operations complete, release the lock
#
lockFree();

#
# Nothing more to do here.
#
exit 0;



#
# lockGet
#
sub lockGet
  {
    return 1 if ("$lockType" eq 'none');
    if ("$lockType" eq 'semaphore')
      {
        $lockSem = IPC::Semaphore->new($lockSemKey, 3, S_IRUSR | S_IWUSR | IPC_CREAT);
        my $i;
        for ($i=0; $i<30; $i++)
          {
            # Use IPC::Shareable / IPC::ShareLite semaphore protocol
            return 1 if ($lockSem->op(1, 0, IPC_NOWAIT,                  # Check for no readers
                                      2, 0, IPC_NOWAIT,                  # Check for no writers
                                      2, 1, (SEM_UNDO | IPC_NOWAIT)));   # Acquire write lock
            print STDERR "Waiting for lock....\n" if ($debug);
            sleep 1;
          }
        return 0;
      }
    else
      {
        mkdir(dirname("$lockFile")) if (! -d dirname("$lockFile"));
        if (open($lockFH, ">$lockFile"))
          {
            my $i;
            for ($i=0; $i<30; $i++)
              {
                return 1 if (flock($lockFH, LOCK_EX | LOCK_NB));
                print STDERR "Waiting for lock.....\n" if ($debug);
                sleep 1;
              }
          }
        return 0;
      }
  }

#
# lockFree
#
sub lockFree
  {
    return 1 if ("$lockType" eq 'none');
    if ("$lockType" eq 'semaphore')
      {
        $lockSem->op(2, -1, (SEM_UNDO | IPC_NOWAIT));
        return 1;
      }
    else
      {
        if (defined($lockFH))
          {
            flock($lockFH, LOCK_UN);
            close($lockFH);
          }
        return 1;
      }
  }

#
# processConfig
#
sub processConfig
  {

    my $cf = shift;

    #
    # If a config file specified, read in the config file
    #
    if (defined($cf) && ("$cf" ne ''))
      {
        my $options = '';
        if (open(FH,"<$cf"))
          {
            my $k; my $v;
            while(<FH>)
              {
                chomp;
                print STDERR "Reading configuration file line: $_\n" if ($debug);
                s/(.*?)\#.*/$1/;         # Remove trailing comments
                next if /^\s*(\#.*)?$/;  # Skip comments and blanks.
                s/^\s+//;
                s/\s+$//;
                $_ = "--" . "$_" if ("$_" !~ /^-/);
                $options = "$options" . ' ' . "$_";
              }
            close(FH);
          }
        if ("$options" ne '')
          {
            if (!GetOptionsFromString($options,
                  "device=s"                 => \$device,
                  "address=s"                => \$address,
                  "delay=f"                  => \$delay,
                  "tdelay=f"                 => \$tdelay,
                  "bdelay=f"                 => \$bdelay,
                  "adelay=f"                 => \$adelay,
                  "ddelay=f"                 => \$ddelay,
                  "rdelay=f"                 => \$rdelay,
                  "idelay=f"                 => \$idelay,
                  "edelay=f"                 => \$edelay,
                  "xmitters|transmitters=i"  => \@transmitters,
                  "beforekeys=s"             => \$before,
                  "afterkeys=s"              => \$after,
                  "digitprefix=s"            => \$digitprefix,
                  "digitnames!"              => \$digitnames,
                  "channeldigits=i"          => \$channeldigits,
                  "channeltransform=s"       => \$channeltransform,
                  "remote=s"                 => \$remote,
                  "locktype=s"               => \$lockType,
                  "lockfilename=s"           => \$lockFile,
                  "lockkey=i"                => \$lockSemKey,
                  "irsend=s"                 => \$irsend,
                  "debug!"                   => \$debug))
              {
                exit 1;
              }
          }
        else
          {
            print "Unable to open the configuration file $cf: $!\n";
            exit 1;
          }
      }

  }


Script.png Configuration file example - Comcast Motorola/Pace DTA

#
# Configuration file for the LircChannelChanger script
#
# Except for the configfile option, all other options
# specified on the command line can be specified in
# this file.  Comments ('#') are stripped, and options
# that are not prefixed with '--' have the '--' added.
#
# The main reason for supporting a configfile is
# that the command line for the ChannelChanger script
# could exceed the 128 character (database) size limits
# if many options were specified (and fully typed out).
# In particular, the before or after commands with long
# remote strings.
#
remote          MotorolaDTA100-PaceDC50X   # lirc remote name
delay           .2          # .2 seconds is long enough for reliable tuning
rdelay          .2          # Add in .2 seconds for debounce compensation
                            # compensation (not clear if needed)
channeldigits   3           # Tunes faster with 3 digits (no timeout reqd)
digitprefix     KEY_        # lirc file has keys prefixed with KEY_
                            # so sending 0 requires the name KEY_0
beforekeys      KEY_INFO    # Return from extended info screen, if on it,
                            # otherwise this puts up the channel info,
                            # which you get anyway when tuning....