예제 #1
0
def geometric_calibration(tv, interactive=True):
    if interactive:
        raw_input("Please line up camera and press <ENTER> when ready")
    tv.show('chessboard')

    sys.stdout.write("Performing Geometric Calibration\n")

    undistorted_appsink = \
        stbt._display.source_pipeline.get_by_name('undistorted_appsink')
    ideal, corners = _find_chessboard(undistorted_appsink)

    undistort = calculate_distortion(ideal, corners, (1920, 1080))
    unperspect = calculate_perspective_transformation(ideal,
                                                      undistort.do(corners))

    geometriccorrection = stbt._display.source_pipeline.get_by_name(
        'geometric_correction')
    geometriccorrection_params = undistort.describe() + unperspect.describe()
    for key, value in geometriccorrection_params:
        geometriccorrection.set_property(key, value)

    validate_transformation(corners, ideal,
                            lambda points: unperspect.do(undistort.do(points)))

    set_config('global', 'geometriccorrection_params',
               ' '.join('%s="%s"' % v for v in geometriccorrection_params))
def geometric_calibration(tv, interactive=True):
    if interactive:
        raw_input("Please line up camera and press <ENTER> when ready")
    tv.show('chessboard')

    sys.stdout.write("Performing Geometric Calibration\n")

    undistorted_appsink = \
        stbt._dut._display.source_pipeline.get_by_name('undistorted_appsink')
    ideal, corners = _find_chessboard(undistorted_appsink)

    undistort = calculate_distortion(ideal, corners, (1920, 1080))
    unperspect = calculate_perspective_transformation(
        ideal, undistort.do(corners))

    geometriccorrection = stbt._dut._display.source_pipeline.get_by_name(
        'geometric_correction')
    geometriccorrection_params = undistort.describe() + unperspect.describe()
    for key, value in geometriccorrection_params:
        geometriccorrection.set_property(key, value)

    validate_transformation(
        corners, ideal, lambda points: unperspect.do(undistort.do(points)))

    set_config(
        'global', 'geometriccorrection_params',
        ' '.join('%s="%s"' % v for v in geometriccorrection_params))
예제 #3
0
def test_that_set_config_creates_directories_if_required():
    with scoped_curdir() as d:
        os.environ['XDG_CONFIG_HOME'] = d + '/.config'
        if 'STBT_CONFIG_FILE' in os.environ:
            del os.environ['STBT_CONFIG_FILE']
        set_config('global', 'test', 'hello2')
        assert os.path.isfile(d + '/.config/stbt/stbt.conf')
        _config_init(force=True)
        assert get_config('global', 'test') == 'hello2'
예제 #4
0
def test_that_set_config_creates_directories_if_required():
    with _directory_sandbox() as d:
        os.environ["XDG_CONFIG_HOME"] = d + "/.config"
        if "STBT_CONFIG_FILE" in os.environ:
            del os.environ["STBT_CONFIG_FILE"]
        set_config("global", "test", "hello2")
        assert os.path.isfile(d + "/.config/stbt/stbt.conf")
        _config_init(force=True)
        assert get_config("global", "test") == "hello2"
예제 #5
0
def test_that_set_config_creates_directories_if_required():
    with scoped_curdir() as d:
        os.environ['XDG_CONFIG_HOME'] = d + '/.config'
        if 'STBT_CONFIG_FILE' in os.environ:
            del os.environ['STBT_CONFIG_FILE']
        set_config('global', 'test', 'hello2')
        assert os.path.isfile(d + '/.config/stbt/stbt.conf')
        _config_init(force=True)
        assert get_config('global', 'test') == 'hello2'
예제 #6
0
def test_that_set_config_writes_to_the_first_stbt_config_file():
    with scoped_curdir() as d:
        filled_cfg = d + '/test.cfg'
        empty_cfg = d + '/empty.cfg'
        os.environ['STBT_CONFIG_FILE'] = '%s:%s' % (filled_cfg, empty_cfg)
        open(filled_cfg, 'w')
        open(empty_cfg, 'w')
        set_config('global', 'test', 'goodbye')
        assert open(filled_cfg).read().startswith('[global]')
        assert open(empty_cfg).read() == ''
예제 #7
0
def test_that_set_config_writes_to_the_first_stbt_config_file():
    with _directory_sandbox() as d:
        filled_cfg = d + "/test.cfg"
        empty_cfg = d + "/empty.cfg"
        os.environ["STBT_CONFIG_FILE"] = "%s:%s" % (filled_cfg, empty_cfg)
        open(filled_cfg, "w")
        open(empty_cfg, "w")
        set_config("global", "test", "goodbye")
        assert open(filled_cfg).read().startswith("[global]")
        assert open(empty_cfg).read() == ""
예제 #8
0
def test_that_set_config_writes_to_the_first_stbt_config_file():
    with scoped_curdir() as d:
        filled_cfg = d + '/test.cfg'
        empty_cfg = d + '/empty.cfg'
        os.environ['STBT_CONFIG_FILE'] = '%s:%s' % (filled_cfg, empty_cfg)
        open(filled_cfg, 'w')
        open(empty_cfg, 'w')
        set_config('global', 'test', 'goodbye')
        assert open(filled_cfg).read().startswith('[global]')
        assert open(empty_cfg).read() == ''
예제 #9
0
def test_that_set_config_preserves_file_comments_and_formatting():
    # pylint:disable=fixme,unreachable
    # FIXME: Preserve comments and formatting.  This is fairly tricky as
    # comments and whitespace are not currently stored in Python's internal
    # ConfigParser representation and multiline values makes just using regex
    # tricky.
    from unittest import SkipTest
    raise SkipTest("set_config doesn't currently preserve formatting")
    with set_config_test():
        set_config('global', 'test', 'goodbye')
        assert open('test.cfg',
                    'r').read() == test_config.replace('hello', 'goodbye')
예제 #10
0
def test_that_set_config_preserves_file_comments_and_formatting():
    # pylint:disable=fixme,unreachable
    # FIXME: Preserve comments and formatting.  This is fairly tricky as
    # comments and whitespace are not currently stored in Python's internal
    # ConfigParser representation and multiline values makes just using regex
    # tricky.
    from unittest import SkipTest
    raise SkipTest("set_config doesn't currently preserve formatting")
    with set_config_test():
        set_config('global', 'test', 'goodbye')
        assert open('test.cfg', 'r').read() == test_config.replace(
            'hello', 'goodbye')
예제 #11
0
def test_that_set_config_preserves_file_comments_and_formatting():
    # pylint:disable=W0511,W0101
    # FIXME: Preserve comments and formatting.  This is fairly tricky as
    # comments and whitespace are not currently stored in Python's internal
    # ConfigParser representation and multiline values makes just using regex
    # tricky.
    from unittest import SkipTest

    raise SkipTest("set_config doesn't currently preserve formatting")
    with set_config_test():
        set_config("global", "test", "goodbye")
        assert open("test.cfg", "r").read() == test_config.replace("hello", "goodbye")
예제 #12
0
def main(argv):
    args = parse_args(argv)

    device = setup(args.source_pipeline)
    if device is None:
        return 1

    if args.skip_geometric:
        set_config('global', 'geometriccorrection_params', '')

    for k, v in defaults.iteritems():
        set_config('global', k, v)

    # Need to re-parse arguments as the settings above may have affected the
    # values we get out.
    args = parse_args(argv)

    transformation_pipeline = (
        'tee name=raw_undistorted '
        'raw_undistorted. ! queue leaky=upstream ! videoconvert ! '
        '    textoverlay text="Capture from camera" ! %s '
        'raw_undistorted. ! queue ! appsink drop=true sync=false qos=false'
        '    max-buffers=1 caps="video/x-raw,format=BGR"'
        '    name=undistorted_appsink '
        'raw_undistorted. ! queue leaky=upstream max-size-buffers=1 ! %s' %
        (args.sink_pipeline,
         stbt.get_config('global', 'transformation_pipeline')))

    args.sink_pipeline = ('textoverlay text="After correction" ! ' +
                          args.sink_pipeline)
    args.control = 'none'

    with _stbt.core.new_device_under_test_from_config(
            args, transformation_pipeline=transformation_pipeline) as dut:
        tv = tv_driver.create_from_args(args, videos)

        if not args.skip_geometric:
            geometric_calibration(dut,
                                  tv,
                                  device,
                                  interactive=args.interactive)
        if args.interactive:
            adjust_levels(dut, tv, device)
        if not args.skip_illumination:
            calibrate_illumination(dut, tv)

        if args.interactive:
            raw_input("Calibration complete.  Press <ENTER> to exit")
        return 0
def main(argv):
    args = parse_args(argv)

    device = setup(args.source_pipeline)
    if device is None:
        return 1

    if args.skip_geometric:
        set_config('global', 'geometriccorrection_params', '')

    for k, v in defaults.iteritems():
        set_config('global', k, v)

    # Need to re-parse arguments as the settings above may have affected the
    # values we get out.
    args = parse_args(argv)

    transformation_pipeline = (
        'tee name=raw_undistorted '
        'raw_undistorted. ! queue leaky=upstream ! videoconvert ! '
        '    textoverlay text="Capture from camera" ! %s '
        'raw_undistorted. ! queue ! appsink drop=true sync=false qos=false'
        '    max-buffers=1 caps="video/x-raw,format=BGR"'
        '    name=undistorted_appsink '
        'raw_undistorted. ! queue leaky=upstream max-size-buffers=1 ! %s' %
        (args.sink_pipeline,
         stbt.get_config('global', 'transformation_pipeline')))

    sink_pipeline = ('textoverlay text="After correction" ! ' +
                     args.sink_pipeline)

    stbt.init_run(args.source_pipeline, sink_pipeline, 'none', False, False,
                  transformation_pipeline)

    tv = tv_driver.create_from_args(args, videos)

    if not args.skip_geometric:
        geometric_calibration(tv, device, interactive=args.interactive)
    if args.interactive:
        adjust_levels(tv, device)
    if not args.skip_illumination:
        calibrate_illumination(tv)

    if args.interactive:
        raw_input("Calibration complete.  Press <ENTER> to exit")
    return 0
def adjust_levels(tv):
    tv.show("colours")
    happy = "no"
    device = stbt.get_config("global", "v4l2_device")
    with colour_graph() as update_graph:
        while not happy.startswith("y"):
            update_graph()

            # Allow adjustment
            subprocess.check_call(["v4l2-ctl", "-d", device, "-L"])
            cmd = raw_input("Happy? [Y/n/set] ").strip().lower()
            if cmd.startswith("set"):
                _, var, val = cmd.split()
                subprocess.check_call(["v4l2-ctl", "-d", device, "-c", "%s=%s" % (var, val)])
            if cmd.startswith("y") or cmd == "":
                break

    set_config("global", "v4l2_ctls", ",".join(["%s=%s" % (c, a["value"]) for c, a in dict(v4l2_ctls(device)).items()]))
def calibrate_illumination(tv):
    img_dir = xdg_config_dir() + "/stbt/"

    props = {
        "white-reference-image": "%s/vignetting-reference-white.png" % img_dir,
        "black-reference-image": "%s/vignetting-reference-black.png" % img_dir,
    }

    tv.show("blank-white")
    await_blank(255)
    _create_reference_png(props["white-reference-image"])
    tv.show("blank-black")
    await_blank(0)
    _create_reference_png(props["black-reference-image"])

    contraststretch = stbt._dut._display.source_pipeline.get_by_name("illumination_correction")
    for k, v in reversed(props.items()):
        contraststretch.set_property(k, v)
    set_config("global", "contraststretch_params", " ".join(["%s=%s" % (k, v) for k, v in props.items()]))
예제 #16
0
def prompt_for_adjustment(device):
    # Allow adjustment
    subprocess.check_call(['v4l2-ctl', '-d', device, '-L'])
    ctls = dict(v4l2_ctls(device))

    def v4l_completer(text):
        if text == '':
            return ['yes', 'no', 'set']
        if text.startswith('set '):
            return [
                'set ' + x + ' ' for x in ctls.keys() if x.startswith(text[4:])
            ]
        if "set ".startswith(text.lower()):
            return ["set "]
        if 'yes'.startswith(text.lower()):
            return ["yes"]
        if 'no'.startswith(text.lower()):
            return ["no"]

    setup_tab_completion(v4l_completer)

    cmd = raw_input("Happy? [Y/n/set] ").strip().lower()
    if cmd.startswith('set'):
        x = cmd.split(None, 2)
        if len(x) != 3:
            print "Didn't understand command %r" % x
        else:
            _, var, val = x
            subprocess.check_call(
                ['v4l2-ctl', '-d', device, "-c",
                 "%s=%s" % (var, val)])

    set_config(
        'global', 'v4l2_ctls', ','.join([
            "%s=%s" % (c, a['value'])
            for c, a in dict(v4l2_ctls(device)).items()
        ]))

    if cmd.startswith('y') or cmd == '':
        return False  # We're done
    else:
        return True  # Continue looping
def chessboard_calibration():
    undistorted_appsink = \
        stbt._dut._display.source_pipeline.get_by_name('undistorted_appsink')
    ideal, corners = _find_chessboard(undistorted_appsink)

    undistort = calculate_distortion(ideal, corners, (1920, 1080))
    unperspect = calculate_perspective_transformation(ideal,
                                                      undistort.do(corners))

    geometriccorrection = stbt._dut._display.source_pipeline.get_by_name(
        'geometric_correction')
    geometriccorrection_params = undistort.describe() + unperspect.describe()
    for key, value in geometriccorrection_params:
        geometriccorrection.set_property(key, value)

    validate_transformation(corners, ideal,
                            lambda points: unperspect.do(undistort.do(points)))

    set_config('global', 'geometriccorrection_params',
               ' '.join('%s="%s"' % v for v in geometriccorrection_params))
def chessboard_calibration(dut, timeout=10):
    from _stbt.gst_utils import array_from_sample

    undistorted_appsink = \
        dut._display.source_pipeline.get_by_name('undistorted_appsink')

    sys.stderr.write("Searching for chessboard\n")
    endtime = time.time() + timeout
    while time.time() < endtime:
        sample = undistorted_appsink.emit('pull-sample')
        try:
            input_image = array_from_sample(sample)
            params = chessboard.calculate_calibration_params(input_image)
            break
        except chessboard.NoChessboardError:
            if time.time() > endtime:
                raise

    geometriccorrection = dut._display.source_pipeline.get_by_name(
        'geometric_correction')

    geometriccorrection_params = {
        'camera-matrix': ('{fx}    0 {cx}'
                          '   0 {fy} {cy}'
                          '   0    0    1').format(**params),
        'distortion-coefficients': '{k1} {k2} {p1} {p2} {k3}'.format(**params),
        'inv-homography-matrix': (
            '{ihm11} {ihm21} {ihm31} '
            '{ihm12} {ihm22} {ihm32} '
            '{ihm13} {ihm23} {ihm33}').format(**params),
    }
    for key, value in geometriccorrection_params.items():
        geometriccorrection.set_property(key, value)

    print_error_map(
        sys.stderr,
        *chessboard.find_corrected_corners(params, input_image))

    set_config(
        'global', 'geometriccorrection_params',
        ' '.join('%s="%s"' % v for v in geometriccorrection_params.items()))
예제 #19
0
def chessboard_calibration(timeout=10):
    from _stbt.gst_utils import array_from_sample

    undistorted_appsink = \
        stbt._dut._display.source_pipeline.get_by_name('undistorted_appsink')

    sys.stderr.write("Searching for chessboard\n")
    endtime = time.time() + timeout
    while time.time() < endtime:
        sample = undistorted_appsink.emit('pull-sample')
        try:
            input_image = array_from_sample(sample)
            params = chessboard.calculate_calibration_params(input_image)
            break
        except chessboard.NoChessboardError:
            if time.time() > endtime:
                raise

    geometriccorrection = stbt._dut._display.source_pipeline.get_by_name(
        'geometric_correction')

    geometriccorrection_params = {
        'camera-matrix': ('{fx}    0 {cx}'
                          '   0 {fy} {cy}'
                          '   0    0    1').format(**params),
        'distortion-coefficients': '{k1} {k2} {p1} {p2} {k3}'.format(**params),
        'inv-homography-matrix': (
            '{ihm11} {ihm21} {ihm31} '
            '{ihm12} {ihm22} {ihm32} '
            '{ihm13} {ihm23} {ihm33}').format(**params),
    }
    for key, value in geometriccorrection_params.items():
        geometriccorrection.set_property(key, value)

    print_error_map(
        sys.stderr,
        *chessboard.find_corrected_corners(params, input_image))

    set_config(
        'global', 'geometriccorrection_params',
        ' '.join('%s="%s"' % v for v in geometriccorrection_params.items()))
def chessboard_calibration():
    undistorted_appsink = \
        stbt._dut._display.source_pipeline.get_by_name('undistorted_appsink')
    ideal, corners = _find_chessboard(undistorted_appsink)

    undistort = calculate_distortion(ideal, corners, (1920, 1080))
    unperspect = calculate_perspective_transformation(
        ideal, undistort.do(corners))

    geometriccorrection = stbt._dut._display.source_pipeline.get_by_name(
        'geometric_correction')
    geometriccorrection_params = undistort.describe() + unperspect.describe()
    for key, value in geometriccorrection_params:
        geometriccorrection.set_property(key, value)

    validate_transformation(
        corners, ideal, lambda points: unperspect.do(undistort.do(points)))

    set_config(
        'global', 'geometriccorrection_params',
        ' '.join('%s="%s"' % v for v in geometriccorrection_params))
def adjust_levels(tv):
    tv.show("colours")
    happy = "no"
    device = stbt.get_config('global', 'v4l2_device')
    with colour_graph() as update_graph:
        while not happy.startswith('y'):
            update_graph()

            # Allow adjustment
            subprocess.check_call(['v4l2-ctl', '-d', device, '-L'])
            cmd = raw_input("Happy? [Y/n/set] ").strip().lower()
            if cmd.startswith('set'):
                _, var, val = cmd.split()
                subprocess.check_call(
                    ['v4l2-ctl', '-d', device, "-c", "%s=%s" % (var, val)])
            if cmd.startswith('y') or cmd == '':
                break

    set_config('global', 'v4l2_ctls', ','.join(
        ["%s=%s" % (c, a['value'])
         for c, a in dict(v4l2_ctls(device)).items()]))
예제 #22
0
def calibrate_illumination(tv):
    img_dir = xdg_config_dir() + '/stbt/'

    props = {
        'white-reference-image': '%s/vignetting-reference-white.png' % img_dir,
        'black-reference-image': '%s/vignetting-reference-black.png' % img_dir,
    }

    tv.show("blank-white")
    await_blank(255)
    _create_reference_png(props['white-reference-image'])
    tv.show("blank-black")
    await_blank(0)
    _create_reference_png(props['black-reference-image'])

    contraststretch = stbt._display.source_pipeline.get_by_name(
        'illumination_correction')
    for k, v in reversed(props.items()):
        contraststretch.set_property(k, v)
    set_config('global', 'contraststretch_params',
               ' '.join(["%s=%s" % (k, v) for k, v in props.items()]))
예제 #23
0
def adjust_levels(tv):
    tv.show("colours")
    happy = "no"
    device = stbt.get_config('global', 'v4l2_device')
    with colour_graph() as update_graph:
        while not happy.startswith('y'):
            update_graph()

            # Allow adjustment
            subprocess.check_call(['v4l2-ctl', '-d', device, '-L'])
            cmd = raw_input("Happy? [Y/n/set] ").strip().lower()
            if cmd.startswith('set'):
                _, var, val = cmd.split()
                subprocess.check_call(
                    ['v4l2-ctl', '-d', device, "-c", "%s=%s" % (var, val)])
            if cmd.startswith('y') or cmd == '':
                break

    set_config('global', 'v4l2_ctls', ','.join(
        ["%s=%s" % (c, a['value'])
         for c, a in dict(v4l2_ctls(device)).items()]))
def calibrate_illumination(tv):
    img_dir = xdg_config_dir() + '/stbt/'

    props = {
        'white-reference-image': '%s/vignetting-reference-white.png' % img_dir,
        'black-reference-image': '%s/vignetting-reference-black.png' % img_dir,
    }

    tv.show("blank-white")
    await_blank(255)
    _create_reference_png(props['white-reference-image'])
    tv.show("blank-black")
    await_blank(0)
    _create_reference_png(props['black-reference-image'])

    contraststretch = stbt._dut._display.source_pipeline.get_by_name(
        'illumination_correction')
    for k, v in reversed(props.items()):
        contraststretch.set_property(k, v)
    set_config(
        'global', 'contraststretch_params',
        ' '.join(["%s=%s" % (k, v) for k, v in props.items()]))
def prompt_for_adjustment(device):
    # Allow adjustment
    subprocess.check_call(['v4l2-ctl', '-d', device, '-L'])
    ctls = dict(v4l2_ctls(device))

    def v4l_completer(text):
        if text == '':
            return ['yes', 'no', 'set']
        if text.startswith('set '):
            return ['set ' + x + ' '
                    for x in ctls.keys() if x.startswith(text[4:])]
        if "set ".startswith(text.lower()):
            return ["set "]
        if 'yes'.startswith(text.lower()):
            return ["yes"]
        if 'no'.startswith(text.lower()):
            return ["no"]

    setup_tab_completion(v4l_completer)

    cmd = raw_input("Happy? [Y/n/set] ").strip().lower()
    if cmd.startswith('set'):
        x = cmd.split(None, 2)
        if len(x) != 3:
            print "Didn't understand command %r" % x
        else:
            _, var, val = x
            subprocess.check_call(
                ['v4l2-ctl', '-d', device, "-c", "%s=%s" % (var, val)])

    set_config('global', 'v4l2_ctls', ','.join(
        ["%s=%s" % (c, a['value'])
         for c, a in dict(v4l2_ctls(device)).items()]))

    if cmd.startswith('y') or cmd == '':
        return False  # We're done
    else:
        return True  # Continue looping
예제 #26
0
def main(argv):
    parser = argparse.ArgumentParser(
        description="Configure stb-tester to use a local X11 program as "
        "input/output.",
        epilog=__doc__,
        formatter_class=argparse.RawDescriptionHelpFormatter)
    subparsers = parser.add_subparsers(dest='subcommand')
    run_parser = subparsers.add_parser('run')
    run_parser.add_argument('-b',
                            '--background',
                            action="store_true",
                            help="Run virtual-stb in background")
    run_parser.add_argument('-v',
                            '--verbose',
                            action="store_true",
                            help="Print xorg logs to console")
    run_parser.add_argument(
        '--x-keymap', help="Filename of file mapping key names to X keysyms")
    run_parser.add_argument('command', nargs=1)
    run_parser.add_argument('args', nargs=argparse.REMAINDER)

    stop_parser = subparsers.add_parser('stop')
    stop_parser.add_argument('-f',
                             '--force',
                             action="store_true",
                             help="Ignore errors")

    args = parser.parse_args(argv[1:])

    if args.subcommand == 'run':
        # Do run our `finally` teardown blocks on SIGTERM
        signal.signal(signal.SIGTERM, lambda _signo, _frame: sys.exit(0))

        write_end = None
        if args.background:
            read_end, write_end = multiprocessing.Pipe(duplex=False)
            pid = os.fork()
            if pid:
                # Parent - wait for child to be ready
                write_end.close()
                read_end.recv()
                return 0
            else:
                # Child
                read_end.close()

        with virtual_stb(args.command + args.args,
                         verbose=args.verbose,
                         x_keymap=args.x_keymap) as (child, config):
            for k, v in config.items():
                set_config('global', k, v)

            try:
                if write_end is not None:
                    write_end.send(True)
                    write_end.close()
                child.wait()
            finally:
                for k in config.keys():
                    set_config('global', k, None)
    elif args.subcommand == 'stop':
        try:
            pid = get_config('global', 'vstb_pid', None)
            set_config('global', 'vstb_pid', None)
            os.kill(int(pid), signal.SIGTERM)
            while True:
                try:
                    os.kill(int(pid), 0)
                    time.sleep(0.1)
                except OSError as e:
                    if e.errno == errno.ESRCH:
                        return 0
                    else:
                        raise
        except Exception:  # pylint: disable=broad-except
            if not args.force:
                raise
예제 #27
0
def test_that_set_config_creates_new_sections_if_required():
    with set_config_test():
        set_config("non_existent_section", "test", "goodbye")
        assert get_config("non_existent_section", "test") == "goodbye"
        _config_init(force=True)
        assert get_config("non_existent_section", "test") == "goodbye"
예제 #28
0
def test_that_set_config_modifies_config_value():
    with set_config_test():
        set_config("global", "test", "goodbye")
        assert get_config("global", "test") == "goodbye"
        _config_init(force=True)
        assert get_config("global", "test") == "goodbye"
예제 #29
0
def main(argv):
    parser = argparse.ArgumentParser(
        description="Configure stb-tester to use a local X11 program as "
                    "input/output.", epilog=__doc__,
        formatter_class=argparse.RawDescriptionHelpFormatter)
    subparsers = parser.add_subparsers(dest='subcommand')
    run_parser = subparsers.add_parser('run')
    run_parser.add_argument('-b', '--background', action="store_true",
                            help="Run virtual-stb in background")
    run_parser.add_argument('-v', '--verbose', action="store_true",
                            help="Print xorg logs to console")
    run_parser.add_argument(
        '--x-keymap', help="Filename of file mapping key names to X keysyms")
    run_parser.add_argument('command', nargs=1)
    run_parser.add_argument('args', nargs=argparse.REMAINDER)

    stop_parser = subparsers.add_parser('stop')
    stop_parser.add_argument('-f', '--force', action="store_true",
                             help="Ignore errors")

    args = parser.parse_args(argv[1:])

    if args.subcommand == 'run':
        # Do run our `finally` teardown blocks on SIGTERM
        signal.signal(signal.SIGTERM, lambda _signo, _frame: sys.exit(0))

        write_end = None
        if args.background:
            read_end, write_end = multiprocessing.Pipe(duplex=False)
            pid = os.fork()
            if pid:
                # Parent - wait for child to be ready
                write_end.close()
                read_end.recv()
                return 0
            else:
                # Child
                read_end.close()

        with virtual_stb(args.command + args.args, verbose=args.verbose,
                         x_keymap=args.x_keymap) as (child, config):
            for k, v in config.items():
                set_config('global', k, v)

            try:
                if write_end is not None:
                    write_end.send(True)
                    write_end.close()
                child.wait()
            finally:
                for k in config.keys():
                    set_config('global', k, None)
    elif args.subcommand == 'stop':
        try:
            pid = get_config('global', 'vstb_pid', None)
            set_config('global', 'vstb_pid', None)
            os.kill(int(pid), signal.SIGTERM)
            while True:
                try:
                    os.kill(int(pid), 0)
                    time.sleep(0.1)
                except OSError as e:
                    if e.errno == errno.ESRCH:
                        return 0
                    else:
                        raise
        except Exception:  # pylint: disable=broad-except
            if not args.force:
                raise
예제 #30
0
def test_that_set_config_modifies_config_value():
    with set_config_test():
        set_config('global', 'test', 'goodbye')
        assert get_config('global', 'test') == 'goodbye'
        _config_init(force=True)
        assert get_config('global', 'test') == 'goodbye'
예제 #31
0
def test_that_set_config_creates_new_sections_if_required():
    with set_config_test():
        set_config('non_existent_section', 'test', 'goodbye')
        assert get_config('non_existent_section', 'test') == 'goodbye'
        _config_init(force=True)
        assert get_config('non_existent_section', 'test') == 'goodbye'
예제 #32
0
def test_that_set_config_creates_new_sections_if_required():
    with set_config_test():
        set_config('non_existent_section', 'test', 'goodbye')
        assert get_config('non_existent_section', 'test') == 'goodbye'
        _config_init(force=True)
        assert get_config('non_existent_section', 'test') == 'goodbye'
예제 #33
0
def test_that_set_config_modifies_config_value():
    with set_config_test():
        set_config('global', 'test', 'goodbye')
        assert get_config('global', 'test') == 'goodbye'
        _config_init(force=True)
        assert get_config('global', 'test') == 'goodbye'