extra/runner/run: Make `exit-status` available to user `post_run` script
extra/runner/run: Save `stbt` version to `stbt-version.log`
extra/runner/server: Serve ".log" files as "text/plain"

When `server` is used to serve all files (i.e. `server` isn't proxied
behind a web server like apache) the browser would download these files
to disk instead of displaying them in the browser.
extra/runner/server: Sort directory listings alphabetically
extra/runner: "Notes" field that can be edited interactively

This is for arbitrary user notes, entered via the web interface.

This information is stored in the file "notes.manual". Unlike
"failure-reason" (created by the automatic classifier script) and
"failure-reason.manual" (containing the text manually entered by the
user), there is no "notes" file, only "notes.manual". There might be
other "*.manual" files in the future, hence the changes to
`Run.__init__` and `Run.read`.
extra/runner/report.py: Cleanup: Move `strip()` into `Run.read`

So that each caller of `Run.read` doesn't have to do it.
extra/runner: Handle unicode input from web form

The javascript in static/edit-testrun.js sends the POST request with
utf-8 encoding (at least according to my tests on Firefox). The
`*.manual` files are only created from such user input via this `server`
script, so they will also always be utf-8.
extra/runner/report: Exit early on invalid arguments

Otherwise this would try to run `report.py $(dirname $arg)/index.html`
to generate the summary report, which would fail with a confusing python
backtrace if the argument was a directory that didn't contain any
testruns.
extra/runner/run: Export `PYTHONUNBUFFERED=x` to user hooks' environment

Setting `PYTHONUNBUFFERED` to any value prevents python from buffering
standard output, which causes wrong timestamps in the log files when a
python script's output is piped through `ts`.

This change means that if any scripts called from `run` (like the
user-specified pre-run, post-run, and classify scripts) use the same
`ts` technique, they won't have to set `PYTHONUNBUFFERED` themselves.
I'll use this in the next commit.
extra/runner/run: If NoVideo, check Blackmagic video-capture hardware freeze

Sometimes the Blackmagic video-capture card fails and never delivers
video again until the PC is rebooted. If this happens we don't continue
running any tests (because they would all fail; restarting the PC
requires human intervention).

We can detect this by running a capture with `GST_DEBUG` enabled. If the
card is functional, then the message "VideoInputFrameArrived" is printed
to stderr *even if the Blackmagic card has no video on its input* (for
example if the set-top box is off). But if the card has failed then the
message is never printed.

For each of the following scenarios the GStreamer debug output looks
like:

* Working Blackmagic card, video source (the system under test) is on:

    activating push
    activatepush
    VideoInputFrameArrived: Frame received [<timecode>] - Valid Frame - Size: <n>

* Working Blackmagic card, video source is off:

    activating push
    activatepush
    VideoInputFrameArrived: Frame received - No input signal detected

  (Sometimes even when the video source is off, you can get
  "VideoInputFrameArrived: Frame received [<timecode>] - Valid Frame".
  Maybe this is only when the Blackmagic card has been configured to
  deliver the last seen frame when there is no video; I'm not sure.)

* Blackmagic card in use by another process (e.g. `stbt tv`):

    enable video input failed

  (and the GStreamer pipeline exits)

* Blackmagic card crashed (requiring a reboot of the PC):

    activating push
    activatepush

  (and the GStreamer pipeline just hangs after that output; eventually a
  stbt function like `wait_for_match` will timeout and raise `NoVideo`).

Note also that this writes to `failure-reason.manual`, because
`failure-reason` can be overwritten if you (manually) re-run `report`.
This Blackmagic failure can only be detected "online" (at the time the
test failed, on the same system that ran the test).
`failure-reason.manual` was introduced in commit 56aa1db9 to store
failure reasons entered manually by the user via the web interface, but
it is useful in this case too. Hopefully the "manual" name isn't too
confusing.

Thanks to Aiman Baharna <aiman.baharna@youview.com> for figuring out
how to detect Blackmagic failures.