This file is indexed.

/usr/lib/2013.com.canonical.certification:checkbox/bin/pulse-active-port-change is in plainbox-provider-checkbox 0.4-1.

This file is owned by root:root, with mode 0o755.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#!/usr/bin/env python3
# This file is part of Checkbox.
#
# Copyright 2014 Canonical Ltd.
# Written by:
#   Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
#
# Checkbox is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 3,
# as published by the Free Software Foundation.
#
# Checkbox is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Checkbox.  If not, see <http://www.gnu.org/licenses/>.
"""
pulse-active-port-change
========================

This script checks if the active port on either sinks (speakers or headphones)
or sources (microphones, webcams) is changed after an appropriate device is
plugged into the DUT. The script is fully automatic and either times out after
30 seconds or returns as soon as the change is detected.

The script monitors pulse audio events with `pactl subscribe`. Any changes to
sinks (or sources, depending on the mode) are treated as a possible match. A
match is verified by running `pactl list sinks` (or `pactl list sources`) and
constructing a set of pairs (sink-source-name, sink-source-active-port). Any
change to the computed set, as compared to the initially computed set, is
considered a match.

Due to the algorithm used, it will also detect things like USB headsets, HDMI
monitors/speakers, webcams, etc.

The script depends on:
    python3-checkbox-support
Which depends on:
    python3-pyparsing
"""
import argparse
import os
import pty
import signal
import subprocess

from checkbox_support.parsers.pactl import parse_pactl_output


class AudioPlugDetection:

    def __init__(self, timeout, mode):
        # store parameters
        self.timeout = timeout
        self.mode = mode
        # get the un-localized environment
        env = dict(os.environb)
        env[b'LANG'] = b''
        env[b'LANGUAGE'] = b''
        env[b'LC_ALL'] = b'C.UTF-8'
        self.unlocalized_env = env
        # set SIGALRM handler
        signal.signal(signal.SIGALRM, self.on_timeout)

    def get_sound_config(self):
        text = subprocess.check_output(
            ["pactl", "list", self.mode],  # either 'sources' or 'sinks'
            env=self.unlocalized_env, universal_newlines=True)
        doc = parse_pactl_output(text)
        cfg = set()
        for record in doc.record_list:
            for attr in record.attribute_list:
                if attr.name == "Active Port":
                    cfg.add((record.name, attr.value))
        return cfg

    def on_timeout(self, signum, frame):
        print("Time is up")
        raise SystemExit(1)

    @classmethod
    def main(cls):
        parser = argparse.ArgumentParser(
            description=__doc__.split("")[0],
            epilog=__doc__.split("")[1],
            formatter_class=argparse.RawDescriptionHelpFormatter)
        parser.add_argument(
            'mode', choices=['sinks', 'sources'],
            help='Monitor either sinks or sources')
        parser.add_argument(
            '-t', '--timeout', type=int, default=30,
            help='Timeout after which the script fails')
        ns = parser.parse_args()
        return cls(ns.timeout, ns.mode).run()

    def run(self):
        found = False
        if self.mode == 'sinks':
            look_for = "Event 'change' on sink #"
        elif self.mode == 'sources':
            look_for = "Event 'change' on source #"
        else:
            assert False
        # Get the initial / baseline configuration
        initial_cfg = self.get_sound_config()
        print("Starting with config: {}".format(initial_cfg))
        print("You have {} seconds to plug something".format(self.timeout))
        # Start the timer
        signal.alarm(self.timeout)
        # run subscribe in a pty as it doesn't fflush() after every event
        pid, master_fd = pty.fork()
        if pid == 0:
            os.execlpe("pactl", "pactl", "subscribe", self.unlocalized_env)
        else:
            child_stream = os.fdopen(master_fd, "rt", encoding='UTF-8')
            try:
                for line in child_stream:
                    if line.startswith(look_for):
                        new_cfg = self.get_sound_config()
                        print("Now using config: {}".format(new_cfg))
                        if new_cfg != initial_cfg:
                            print("It seems to work!")
                            found = True
                            break
            except KeyboardInterrupt:
                pass
            finally:
                os.kill(pid, signal.SIGTERM)
                os.close(master_fd)
        return 0 if found else 1


if __name__ == "__main__":
    raise SystemExit(AudioPlugDetection.main())