# Object Interest

The Interest object allows you to declare interest in a specific object, or a set of objects, and filter them. This is used in the ObjectManager but also in other places where methods allow you to iterate over a set of objects or lookup a specific object.

Interest is a binding of `WpObjectInterest`, but it uses a Lua-idiomatic way of construction instead of mapping directly the C functions, for convenience.

## Construction

The most common use for Interest is in the ObjectManager, where you have to use the following construction method to create it.

Interest(decl)
  Parameters:

    decl (table) -- an interest declaration

  Returns:

    the interest

  Return type:

    Interest (`WpObjectInterest`)

The interest consists of a GType and an array of constraints. It is constructed with a table that contains all the constraints, plus the GType in the `type` field.

    local om = ObjectManager {
      Interest {
        type = "node",
        Constraint { "node.name", "matches", "alsa*", type = "pw-global" },
        Constraint { "media.class", "equals", "Audio/Sink", type = "pw-global" },
      }
    }

In the above example, the interest will match all objects of type `WpNode` that contain the following 2 global properties:

> - "node.name", with a value that begins with the string "alsa"

> - "media.class", with a value that equals exactly the string "Audio/Sink"

When an object method requires an Interest as an argument, you may as well directly pass the declaration table as argument instead of using the `Interest()` constructor function. For instance,

    local fl_port = node:lookup_port {
      Constraint { "port.name", "equals", "playback_FL" }
    }

In the above example, we lookup a port in a node. The `Node.lookup_port()` method takes an Interest as an argument, but we can pass the interest declaration table directly. Note also that such a method does not require declaring the `type` of the interest, as it has `WpPort` as a hardcoded default.

### The type

The type of an interest must be a valid GType, written as a string without the "Wp" prefix and with the first letter optionally being lowercase. The type may match any wireplumber object or interface.

Examples:

type string | parsed as
--- | ---
node | WpNode
Node | WpNode
device | WpDevice
plugin | WpPlugin
siLink | WpSiLink
SiLink | WpSiLink
properties | WpProperties

### The Constraint

The Constraint is constructed also with a table, like Interest itself. This table must have the following items in this very strict order:

> - a subject string: a string that specifies the name of a property to match

> - a verb string: a string that specifies the match operation

> - an object, if the verb requires it

The verb may be any verb listed in `WpConstraintVerb`, using either the nickname of the enum or the character value of it.

Allowed verbs:

nickname | character | value
--- | --- | ---
"equals" | "=" | `WP_CONSTRAINT_VERB_EQUALS`
"not-equals" | "!" | `WP_CONSTRAINT_VERB_NOT_EQUALS`
"in-list" | "c" | `WP_CONSTRAINT_VERB_IN_LIST`
"in-range" | "~" | `WP_CONSTRAINT_VERB_IN_RANGE`
"matches" | "#" | `WP_CONSTRAINT_VERB_MATCHES`
"is-present" | "+" | `WP_CONSTRAINT_VERB_IS_PRESENT`
"is-absent" | "-" | `WP_CONSTRAINT_VERB_IS_ABSENT`

The values that are expected for each verb are primarily documented in `wp_object_interest_add_constraint()`. In Lua, though, native types are expected instead of GVariant and then they are converted according to the rules documented in the GObject Integration page.

Examples of constraints:

    Constraint { "node.id", "equals", "42" }
    Constraint { "node.id", "equals", 42 }
    Constraint { "port.physical", "=", true }

    Constraint { "audio.channel", "not-equals", "FL" }

    Constraint { "node.name", "matches", "v4l2_input*" }
    Constraint { "format.dsp", "#", "*mono audio*" }

    -- matches either "default" or "settings" as a possible value for "metadata.name"
    Constraint { "metadata.name", "in-list", "default", "settings" }

    -- matches any priority.session between 0 and 1000, inclusive
    Constraint { "priority.session", "in-range", 0, 1000 }

    -- matches when the object has a "media.role" property
    Constraint { "media.role", "is-present" }

    -- matches when "media.role" is not present in the properties list
    Constraint { "media.role", "is-absent" }

### Constraint types

PipeWire objects have multiple properties lists, therefore constraints also need to have a way to specify on which property list they apply. The constraint type may be any of the types listed in `WpConstraintType` and can be specified with an additional field in the Constraint construction table, called `type`.

For instance:

    Constraint { "node.id", "equals", "42", type = "pw-global" }
    Constraint { "api.alsa.card.name", "matches", "*Intel*", type = "pw" }
    Constraint { "bound-id", "=", 42, type = "gobject" }

Valid types are:

type | value
--- | ---
pw-global | `WP_CONSTRAINT_TYPE_PW_GLOBAL_PROPERTY`
pw | `WP_CONSTRAINT_TYPE_PW_PROPERTY`
gobject | `WP_CONSTRAINT_TYPE_G_PROPERTY`

## Methods

Interest.matches(self, obj)

  Binds `wp_object_interest_matches()`

  Checks if a specific object matches the interest. The object may be a GObject or a table convertible to `WpProperties`, if the interest is for properties.

  This is rarely useful to use directly on objects, but it may be useful to check if a specific table contains key-value pairs that match specific constraints, using "properties" as the interest type and passing a table as the object.

  Parameters:

    - self -- the interest

    - obj (GObject or table) -- an object to check for a match

  Returns:

    whether the object matches the interest

  Return type:

    boolean