Example #1
0
class PortWithProfile(Node):
    """
    Variant of :class:`Port` that is used by "card" records inside
    the "Ports" property. It differs from the normal port syntax by having
    different entries inside the last section. Availability is not listed
    here, only priority. Priority does not have a colon before the actual
    number. This port is followed by profile assignment.
    """
    __fragments__ = {
        'name': 'port-name',
        'label': 'port-label',
        'priority': 'port-priority',
        'latency_offset': 'port-latency-offset',
        'availability': 'port-availability',
        'properties': lambda t: t['port-properties'].asList(),
        'profile_list': lambda t: t['port-profile-list'].asList(),
    }

    __syntax__ = (
        p.Word(p.alphanums + "-;").setResultsName('port-name') +
        p.Suppress(':')
        # This part was very tricky to write. The label is basically arbitrary
        # localized Unicode text. We want to grab all of it in one go but
        # without consuming the upcoming and latest '(' character or the space
        # that comes immediately before.
        #
        # The syntax here combines a sequence of words, as defined by anything
        # other than a space and '(', delimited by a single whitespace.
        + p.Combine(
            p.OneOrMore(~p.FollowedBy(p.Regex('\(.+?\)') + p.LineEnd()) +
                        p.Regex('[^ \n]+') + p.White().suppress()),
            ' ').setResultsName('port-label') + p.Suppress('(') +
        p.Keyword('priority').suppress() + p.Optional(p.Suppress(':')) +
        p.Word(p.nums).setParseAction(lambda t: int(t[0])).setResultsName(
            'port-priority') + p.Optional(
                p.MatchFirst([
                    p.Suppress(',') + p.Keyword('latency offset:').suppress() +
                    p.Word(p.nums).setParseAction(lambda t: int(t[0])) +
                    p.Literal("usec").suppress(),
                    p.Empty().setParseAction(lambda t: '')
                ]).setResultsName('port-latency-offset')) + p.Optional(
                    p.MatchFirst([
                        p.Suppress(',') + p.Literal('not available'),
                        p.Suppress(',') + p.Literal('available'),
                        p.Empty().setParseAction(lambda t: '')
                    ]).setResultsName('port-availability')) + p.Suppress(')') +
        p.LineEnd().suppress() + p.Optional(
            p.MatchFirst([
                p.LineStart().suppress() + p.NotAny(p.White(' ')) +
                p.White('\t').suppress() + p.Keyword('Properties:').suppress()
                + p.LineEnd().suppress() + PropertyAttributeValue,
                p.Empty().setParseAction(lambda t: [])
            ]).setResultsName('port-properties')) +
        p.White('\t', max=3).suppress() +
        p.Literal("Part of profile(s)").suppress() + p.Suppress(":") +
        p.delimitedList(
            p.Word(p.alphanums + "+-:"),
            ", ").setResultsName("port-profile-list")).setResultsName("port")
Example #2
0
class Profile(Node):
    """
    Description of a pulseaudio profile.
    """

    __fragments__ = {
        'name': 'profile-name',
        'label': 'profile-label',
        'sink_cnt': 'profile-sink-count',
        'source_cnt': 'profile-source-count',
        'priority': 'profile-priority',
    }

    __syntax__ = (
        p.Word(p.alphanums + "+-:").setParseAction(
            lambda t: t[0].rstrip(':')).setResultsName("profile-name") +
        p.delimitedList(
            p.Literal("(HDMI)") | p.Literal("(IEC958)") | p.Regex('[^ (\n]+'),
            ' ',
            combine=True).setResultsName('profile-label') + p.Suppress('(') +
        p.Keyword('sinks').suppress() + p.Suppress(':') +
        p.Word(p.nums).setParseAction(lambda t: int(t[0])).setResultsName(
            'profile-sink-count') + p.Suppress(',') +
        p.Keyword('sources').suppress() + p.Suppress(':') +
        p.Word(p.nums).setParseAction(lambda t: int(t[0])).setResultsName(
            'profile-source-count') + p.Suppress(',') +
        p.Keyword('priority').suppress() + p.MatchFirst([
            p.Suppress('.'),
            # http://cgit.freedesktop.org/pulseaudio/pulseaudio/commit/src/utils/pactl.c?id=83c3cf0a65fb05900f81bd2dbb38e6956eb23935
            p.Suppress(':'),
        ]) + p.Word(p.nums).setParseAction(lambda t: int(t[0])).setResultsName(
            'profile-priority') + p.Suppress(')')).setResultsName("profile")
Example #3
0
class Port(Node):
    """
    Description of a port on a sink
    """

    __fragments__ = {
        'name': 'port-name',
        'label': 'port-label',
        'priority': 'port-priority',
        'availability': 'port-availability'
    }

    __syntax__ = (
        p.Word(p.alphanums + "-;").setResultsName('port-name') +
        p.Suppress(':')
        # This part was very tricky to write. The label is basically
        # arbitrary localized Unicode text.  We want to grab all of it in
        # one go but without consuming the upcoming '(' character or the
        # space that comes immediately before.
        #
        # The syntax here combines a sequence of words, as defined by
        # anything other than a space and '(', delimited by a single
        # whitespace.
        + p.delimitedList(p.Regex('[^ (\n]+'), ' ',
                          combine=True).setResultsName('port-label') +
        p.Suppress('(') + p.Keyword('priority').suppress() + p.Suppress(':') +
        p.Word(p.nums).setParseAction(lambda t: int(t[0])).setResultsName(
            'port-priority') + p.MatchFirst([
                p.Suppress(',') + p.Literal('not available'),
                p.Suppress(',') + p.Literal('available'),
                p.Empty().setParseAction(lambda t: '')
            ]).setResultsName('port-availability') +
        p.Suppress(')')).setResultsName("port")
Example #4
0
class Record(Node):
    """
    Single standalone entry of `pactl list`.

    The record is composed of a name and a list of attributes.  Pulseaudio
    exposes objects such as cards, sinks and sources as separate records.

    Each attribute may be of a different type. Some attributes are simple
    values while others have finer structure, including lits and even
    additional recursive attributes.
    """

    __fragments__ = {
        'name':
        'record-name',
        'attribute_list':
        lambda t: t['record-attributes'].asList(),
        'attribute_map':
        lambda t: OrderedDict(
            (attr.name, attr) for attr in t['record-attributes'].asList()),
    }

    __syntax__ = (
        p.LineStart() + p.NotAny(p.White(' \t')) +
        p.Regex("[A-Z][a-zA-Z ]+ #[0-9]+").setResultsName("record-name") +
        p.LineEnd().suppress() + p.OneOrMore(
            p.Or([
                GenericListAttribute.Syntax,
                GenericSimpleAttribute.Syntax,
            ])).setResultsName("record-attributes")).setResultsName("record")

    def as_json(self):
        return {
            'name': self.name,
            'attribute_list': self.attribute_list,
        }

    def __repr__(self):
        # Custom __repr__ that skips attribute_map
        return "{}({})".format(
            type(self).__name__, ", ".join([
                "{}={!r}".format(attr, getattr(self, attr))
                for attr in ['name', 'attribute_list']
            ]))
Example #5
0
                p.White('\t').suppress() + p.Keyword('Properties:').suppress()
                + p.LineEnd().suppress() + PropertyAttributeValue,
                p.Empty().setParseAction(lambda t: [])
            ]).setResultsName('port-properties')) +
        p.White('\t', max=3).suppress() +
        p.Literal("Part of profile(s)").suppress() + p.Suppress(":") +
        p.delimitedList(
            p.Word(p.alphanums + "+-:"),
            ", ").setResultsName("port-profile-list")).setResultsName("port")


# =========================
# Non-collection attributes
# =========================

AttributeName = p.Regex("[a-zA-Z][^:\n]+").setResultsName("attribute-name")

VolumeAttributeValue = (p.Combine(
    p.Or([p.Literal("(invalid)"),
          p.Regex("([0-9]+: +[0-9]+% ?)+")]) + p.LineEnd() +
    p.Optional(p.White('\t').suppress()) +
    p.Or([p.Literal("(invalid)"),
          p.Regex("([0-9]+: -?[0-9]+\.[0-9]+ dB ?)+")]) + p.LineEnd() +
    p.Optional(p.White('\t').suppress()) + p.Regex("balance [0-9]+\.[0-9]+") +
    p.LineEnd(),
    adjacent=False).setResultsName("attribute-value"))

BaseVolumeAttributeValue = (p.Combine(
    p.Regex("[0-9]+%") + p.LineEnd() + p.Optional(p.White('\t').suppress()) +
    p.Regex("-?[0-9]+\.[0-9]+ dB") + p.LineEnd(),
    adjacent=False).setResultsName("attribute-value"))