# Spa Device

There are two kinds of device objects in the Lua API.

A `Device` is a proxy to a struct pw_device that lives in the PipeWire daemon; it binds WpDevice and behaves like any other proxy (see PipeWire Proxies).

A `SpaDevice` binds WpSpaDevice and runs a SPA device implementation inside the WirePlumber process. This is what all the shipped device monitors are built on: the SPA plugin discovers hardware and asks, via the `create-object` signal, for objects to be created; the script decides what to actually create and hands the result back with `SpaDevice.store_managed_object()`. A `SpaDevice` is therefore both a device monitor (`api.alsa.enum.udev`, `api.bluez5.enum.dbus`, `api.v4l2.enum.udev`, ...) and, one level down, each individual device that such a monitor asks to be created.

## Constructors

Device(factory, properties)

  Binds `wp_device_new_from_factory()`

  Creates a device on the PipeWire server by asking the remote factory factory to create it. The device only exists on the server once `Feature.Proxy.BOUND` has been activated; see WpObject.

  Parameters:

    - factory (string) -- the name of the PipeWire factory

    - properties -- (optional) a table or Properties object with the device properties

  Returns:

    the new device, or nil if the core is not connected

  Return type:

    Device

SpaDevice(factory, properties)

  Binds `wp_spa_device_new_from_spa_factory()`

  Loads the SPA factory factory from the SPA plugins and wraps the spa_device object that it creates.

  The returned object does nothing until it is activated with `Feature.SpaDevice.ENABLED`; see WpObject. Connect to the signals below before activating, otherwise the objects that the device creates on startup are missed. For real devices, as opposed to device monitors, it is also desirable to export the device to PipeWire by activating `Feature.Proxy.BOUND` at the same time.

  Example:

      local device = SpaDevice("api.alsa.enum.udev", properties)
      if device then
        device:connect("create-object", createDevice)
        device:connect("object-removed", removeDevice)
        device:activate(Feature.SpaDevice.ENABLED)
      end

  Parameters:

    - factory (string) -- the name of the SPA factory

    - properties -- (optional) a table or Properties object with the device properties

  Returns:

    the new spa device, or nil if the factory could not be loaded

  Return type:

    SpaDevice

## Signals

A `SpaDevice` emits the signals of `WpSpaDevice`, which are connected with `GObject.connect()`:

`create-object` (self, id, type, factory, properties)

  The device is asking for a managed object to be created. The handler is expected to construct the object using the requested factory and properties and to store it with `SpaDevice.store_managed_object()` under the same id. Objects that are created asynchronously, which is normally the case, should be marked with `SpaDevice.set_managed_pending()` first and stored once they are ready.

`object-removed` (self, id)

  The device has deleted the managed object id. The handler may release any additional resources associated with it. There is no need to remove the object with `SpaDevice.store_managed_object()`; that happens internally right after this signal.

`event` (self, pod)

  The device emitted an event, as a Spa Pod object.

## Methods

SpaDevice.iterate_params(self, param_name, filter)

  Binds `wp_spa_device_enum_params_sync()`

  Parameters:

    - self -- the spa device

    - param_name (string) -- the SPA param name to enumerate, ex "EnumProfile"

    - filter (Pod) -- (optional) a Spa Pod object to filter the results

  Returns:

    the available parameters

  Return type:

    Iterator; the iteration items are Spa Pod objects

SpaDevice.set_param(self, param_name, pod)

  Binds `wp_spa_device_set_param()`

  Parameters:

    - self -- the spa device

    - param_name (string) -- the SPA param name to set, ex "Profile"

    - pod (Pod) -- a Spa Pod object containing the new params

SpaDevice.iterate_managed_objects(self)

  Binds `wp_spa_device_new_managed_object_iterator()`

  Parameters:

    self -- the spa device

  Returns:

    all the objects that are currently stored on this device

  Return type:

    Iterator

SpaDevice.get_managed_object(self, id)

  Binds `wp_spa_device_get_managed_object()`

  Parameters:

    - self -- the spa device

    - id (integer) -- the object id

  Returns:

    the managed object or nil

SpaDevice.store_managed_object(self, id, object)

  Binds `wp_spa_device_store_managed_object()`

  Stores an object under id, taking ownership of it. Storing nil destroys the object that was previously stored under this id.

  Parameters:

    - self -- the spa device

    - id (integer) -- the object id

    - object (GObject) -- a GObject to store or nil to remove the existing stored object

SpaDevice.set_managed_pending(self, id)

  Binds `wp_spa_device_set_managed_pending()`

  Marks id as pending, meaning that an object for it is being created but is not ready yet. Params that the device sets on the object in the meantime are saved and applied as soon as `SpaDevice.store_managed_object()` provides the object. Without this, the settings that a device applies to a node right after asking for it to be created are lost.

  This has no effect if an object is already stored under id.

  Parameters:

    - self -- the spa device

    - id (integer) -- the object id