stbt.py: Support multiple lirc devices connected to the same host

To use multiple LIRC devices connected to the same host:

(1) Stop and disable lirc service:

sudo systemctl stop lirc.service
sudo systemctl disable lirc.service

(2) Run multiple `lircd` instances, and set the TCP ports that each
device listens to:

sudo lircd --device=/dev/lirc0 --pidfile=/var/run/lirc/lirc0.pid \
    --listen=8700 --output=/var/run/lirc/lircd
sudo lircd --device=/dev/lirc1 --pidfile=/var/run/lirc/lirc1.pid \
    --listen=8701

lirc0 and lirc1 can be addressed individually using the assigned TCP
ports.

(3) Send keys by sending a LIRC command string to the TCP socket:

echo -e "SEND_ONCE humax MENU" | nc localhost 8765

It's also possible to output keys via a LIRC device of a remote computer.

(4) To auto-launch lircd when a new device is attached, and auto-kill it
when the device is removed, add the following to
/etc/udev/rules.d/10-local.rules:

ACTION=="add", KERNEL=="lirc*", RUN+="/usr/bin/sh -c '/usr/sbin/lircd --device=/dev/$kernel --listen=$((8700 + $number)) --pidfile=/var/run/lirc/$kernel.pid 2>&1 | xargs -rL1 logger'"
ACTION=="remove", KERNEL=="lirc*", RUN+="/usr/bin/sh -c 'kill $(</var/run/lirc/$kernel.pid) 2>&1 | xargs -rL1 logger'"

Make sure not to break a rule to multiple lines.

It starts lircd listener on port (8700 + N) where 'N' is the device
number as in /dev/lircN. Errors are logged to /var/log/messages.

(These instructions were tested with Fedora 17.)

* * *

To put both IR devices into use by stb-tester, all we need is a new
remote type with "hostname", "port" and "remote_control_name" parameters
that uses 'VirtualRemote._connect' to connect and 'LircRemote.press' to
send keys. Similarly, for recording, a new listener type that uses
'VirtualRemote._connect' to connect and 'lirc_key_reader' to interpret
remote keys.

Closes #9.
README: Add Travis CI build status icon

So that the build status will be visible in the GitHub web interface
at https://github.com/drothlis/stb-tester (which displays the README
in the main project page).

travis-ci.org is a free Continuous Integration service -- see commit
b08660e5 for details.

When we generate the stbt man page from this README, we have to remove
this image, because man pages can't have images and we'd end up with
an ugly placeholder instead.
Disable annoying pylint warnings

Disable the following pylint warnings:

* All "C" conventions, because some of them (like "missing docstring")
  are too draconic. The exception is C0301 (line too long) which we do
  want to enforce. In fact, enabling the "line too long" check was the
  initial motivation for enabling pylint warnings in 1276c4e3.

* All "R" refactor warnings, because I don't believe code quality can be
  automatically measured by things like "a class must have at least two
  public methods".

I didn't find any way of wrapping the "disable" line in pylint.conf: A
trailing "\" doesn't work, nor does specifying "disable" multiple times
on different lines.

Use "pylint --list-msgs" for a description of all possible warnings.
Use "pylint --help-msg C0301" for a description of a particular warning.

Note that "pylint: enable=C0111" doesn't actually work now that C0111 is
disabled in pylint.conf, so I've removed those comments; these public
functions all have docstrings already.
Remove some pylint inline comments

Instead of telling pylint to ignore W0613 (unused argument), name
the argument with a leading underscore; this also causes pylint to
ignore it.

And fix string escapes to comply with the python spec, instead of
ignoring W1401 (anomalous backslash in string).
stbt templatematch: Run the image processing algorithm at most once

By using `detect_match` to process a single frame instead of relying on
a `wait_for_match` timeout of 1 second, we decrease the run time for the
no-match case to 60% of the original run time (on my dual-core 1.8GHz
Intel Core i7).
minor fix: reference to `noise_threshold` changed to `confirm_threshold`

Since 18a5e70e, the parameter `noise_threshold` has been marked for
deprecation in favour of using `confirm_threshold` instead.
Merge pull request #22 from LewisHaley/minor-fix

minor fix: reference to `noise_threshold` changed to `confirm_threshold`
Configuration in tool-specific sections no longer overrides "global" section

This affects the loading of default values from the configuration file
for "stbt run" and "stbt record", and the behaviour of the python
function "stbt.get_config" and of the command-line utility
"stbt config".

Note that configuration items that are only used by a single tool still
remain in the tool-specific section. Those items now must be in the
tool-specific section; they won't be searched for in the "global"
section.

UPGRADING
=========

This is a non-backwards-compatible change. If you had customised your
config file, you will need to ensure it complies with the new expected
layout:

* Move these entries from the "[run]" or "[record]" sections to the
  "[global]" section:

  - control
  - source_pipeline
  - sink_pipeline
  - verbose

* This entry must be in the "[run]" section:

  - script

* These entries must be in the "[record]" section:

  - output_file
  - control_recorder

BACKGROUND
==========

The tools like "stbt run" and "stbt record" take parameters on the
command line, like "--source-pipeline". If not specified on the command
line, the value is taken from the configuration file(s). In a typical
installation, the following files are searched:

* /etc/stbt/stbt.conf
* ~/.config/stbt/stbt.conf
* $STBT_CONFIG_FILE

(with later files taking precedence).

These files use the "ini" format:

    [section]
    key = value

Prior to this commit, "stbt run" searches for each configuration item
(e.g. "source_pipeline") in the "[run]" section; if not found, then it
searches in the "[global]" section.

The confusing behaviour was that "[run] source_pipeline" specified in
/etc/stbt/stbt.conf would override "[global] source_pipeline" specified
in ~/.config/stbt/stbt.conf (note that if both items were specified in
the same section, the precedence would be the opposite order).

Nobody actually uses this "feature" -- there hasn't been a need for a
particular tool to override the global configuration used by all other
tools.
test_get_config: Test all possible failures

Previously, the line `stbt.get_config("no_such_key")` would fail
(as expected) and jump to the `except` block; so the other two
`stbt.get_config` lines weren't tested at all.

This also catches `ConfigurationError` explicitly (instead of all
exceptions) to test that `stbt.get_config` is throwing the correct
exception type.
stbt.get_config: Cleanup: Remove `load_config` helper function
stbt.get_config: Handle all ConfigParser errors

...and use ConfigParser's own error messages:

* No option 'no_such_key' in section: 'global'
* No section: 'no_such_section'
etc.

Note that ConfigParser supports interpolation, so values can refer to
other values, e.g.

    [My Section]
    foodir: %(dir)s/whatever
    dir=frob

so there are many possible ConfigParser exception types other than
NoSectionError and NoOptionError.
stbt.py: `mock_get_config` returns same types as real `get_config`

(in `test_build_templatematch_params_detects_undefined`).

This doesn't really affect the test; it's just for consistency with
the real `get_config`.
Merge branch 'config-sections'

The important functional change is 9283df1 (Configuration in
tool-specific sections no longer overrides "global" section).

* config-sections:
  stbt.py: `mock_get_config` returns same types as real `get_config`
  stbt.get_config: Handle all ConfigParser errors
  stbt.get_config: Cleanup: Remove `load_config` helper function
  test_get_config: Test all possible failures
  Configuration in tool-specific sections no longer overrides "global" section
api-doc.sh: Cleanup: Remove unused function
stbt.get_config: Explicitly cast return value to `str`

`ConfigParser.get` always returns a string already, but this helps
`pylint` (a static analyser), which otherwise would fail when run on a
script that calls `stbt.get_config(...).split(":")`:

    xxx.py:nnn: [E1103] Instance of '_Chainmap' has no 'startswith'
                member (but some types could not be inferred)
`wait_for_match` etc: Fix race condition when specifying match parameters

This was manifesting as intermittent failures of the test
`test_wait_for_match_confirm_methods_produce_different_results`.

This is issue #24: https://github.com/drothlis/stb-tester/issues/24

The race condition is that the `template` property of the
`stbt-templatematch` GStreamer element is being set *before* setting the
`confirmMethod` property. Sometimes the GStreamer element manages to
process one frame using the new template, and post a message, before the
`confirmMethod` property is set. The default `confirmMethod` value
causes a different match result than what we expect with the value we
wanted to set.

HOW I DIAGNOSED IT
==================

This was easy to diagnose with the following patch:

   diff --git a/gst/gsttemplatematch.c b/gst/gsttemplatematch.c
   index bd115e2..6642b81 100644
   --- a/gst/gsttemplatematch.c
   +++ b/gst/gsttemplatematch.c
   @@ -503,6 +503,10 @@ gst_templatematch_chain (GstPad * pad, GstBuffer * buf)
          matched = FALSE;
        }

   +    printf("*** matched: %s\n", matched ? "true" : "false");
   +    printf("*** confirmMethod: %d\n", filter->confirmMethod);
   +    printf("*** template: %s\n", filter->template);
   +
        s = gst_structure_new ("template_match",
            "x", G_TYPE_UINT, best_pos.x,
            "y", G_TYPE_UINT, best_pos.y,

I got the following output:

    stbt-run: Searching for tests/known-fail-template.png
    *** matched: true
    *** confirmMethod: 1
    *** template: tests/known-fail-template.png
    *** matched: false
    *** confirmMethod: 2
    *** template: tests/known-fail-template.png

THINGS THAT DIDN'T WORK
=======================

    diff --git a/stbt.py b/stbt.py
    index 646b758..4aa18bf 100644
    --- a/stbt.py
    +++ b/stbt.py
    @@ -754,8 +754,7 @@ def Display.detect:
                 properties_backup[key] = getattr(element.props, key)

             try:
    -            for key in properties.keys():
    -                setattr(element.props, key, properties[key])
    +            element.set_properties(**properties)

                 # Timeout after 10s in case no messages are received on the bus.
                 # This happens when starting a new instance of stbt when the

It seems that `set_properties` doesn't set all properties atomically.

    diff --git a/stbt.py b/stbt.py
    index c5ddd26..bcdaf08 100644
    --- a/stbt.py
    +++ b/stbt.py
    @@ -655,8 +655,10 @@ def Display.detect
                 params_backup[key] = getattr(element.props, key)

             try:
    +            self.pipeline.set_state(gst.STATE_PAUSED)
                 for key in params.keys():
                     setattr(element.props, key, params[key])
    +            self.pipeline.set_state(gst.STATE_PLAYING)

                 # Timeout after 10s in case no messages are received on the bus.
                 # This happens when starting a new instance of stbt when the

Pausing the pipeline while we set the properties didn't make any
difference either. Maybe the `set_state` function doesn't block until
the pipeline is actually paused?

THE FIX
=======

This fix simply sets the `template` property after all the other
properties. This works because `detect_match` discards messages from the
GStreamer element if the message's `template` field doesn't match the
template we are looking for.

We do the same for the `enabled` property of the `stbt-motiondetect`
GStreamer element used by `detect_motion`. Note that
`stbt-templatematch` doesn't have an `enabled` property, because the
`template` property serves the same purpose.

This is a *temporary* fix because, in theory, the GStreamer element
could have posted a message *after* we've stopped reading messages but
before we set the `template` property back to null. If the next
`wait_for_match` uses the same template but with different match
parameters, it might read the old message from the bus and mistakenly
accept it.

A more robust fix would be to set some serial number property (*after*
setting the new template and all match-parameter properties), have the
GStreamer element include this serial number in the messages it posts,
and have the python application check that the serial number in the
messages matches the value it set.
gsttemplatematch.c: GStreamer element documentation comment

I have no idea where the "#" and "%" notation comes from; I just copied
the notation from gstmotiondetect.c. The closest I found was by googling
for "gobject doc comments" which found this:
https://live.gnome.org/GObjectIntrospection/Annotations

which doesn't actually describe the "#" notation anywhere but does use
it in a couple of examples to refer to a type. Note though that the
above url refers to GObjectIntrospection which is fairly new; for
example it's used by GStreamer 1.0 but not by GStreamer 0.10 (the
version stb-tester uses).
stbt.get_config API change from (key, section='global') to (section, key)

This changes the python API to:

    stbt.get_config(section, key)

Since 9283df1, `get_config` no longer falls back to the "global" config
section, so it makes less sense to provide a default `section`. The
change in parameter order is more consistent with python's
`ConfigParser`, and with our command-line tool `stbt config` (and other
similar command-line tools like `git config`).

I wanted to make this API change now, before there are too many users of
`stbt.get_config`. `stbt.get_config` was only added in the previous
stb-tester release (0.12). Hopefully most users were only passing one
parameter, so now that the second parameter doesn't have a default value
you'd find the API change by running `pylint`. If they were using the
keyword parameter (in 0.12 it was called "tool" instead of "section")
then pylint will also catch the change. Otherwise there will be a
run-time failure because it's highly unlikely you'll have a section in
your config file matching the key you're looking for, with a key
matching the section you're looking for.
stbt config: Nicer error messages
stbt config: API change from `[section] key` to `section.key`

This changes the command-line tool's API to:

    stbt config <section>.<key>

Since 9283df1, the search for a configuration key no longer falls back
to the "global" config section, so it makes less sense to provide a
default section. The new API is consistent with `git config`, and it
will allow us (in future) to add a parameter to specify the default
value should the key not be found in the configuration files.

I wanted to make this change now, before there are too many users of
`stbt config` (which was only added in the previous stb-tester release,
0.12). All current users of the tool will fail: Those specifying two
parameters will fail because now only one parameter is allowed; those
specifying a single parameter will fail because that parameter doesn't
include the section and the key name separated by a dot. So at least
there won't be any confusing silent changes in behaviour.