# (c) 2026 Applied Brain Research
#
# All information contained herein is and remains the property of Applied Brain
# Research. The intellectual and technical concepts contained herein are
# proprietary to Applied Brain Research and may be covered by U.S. and Foreign
# Patents, patents in process, and are protected by trade secret or copyright
# law. Dissemination of this information or reproduction of this material is
# strictly forbidden unless prior written permission is obtained from Applied
# Brain Research. Access to the source code contained herein is hereby
# forbidden to anyone except current Applied Brain Research employees,
# contractors or other outside parties that have executed Confidentiality
# and/or Non-disclosure agreements explicitly covering such access.
#
# The copyright notice above does not evidence any actual or intended
# publication or disclosure of this source code, which includes information
# that is confidential and/or proprietary, and is a trade secret, of Applied
# Brain Research. ANY REPRODUCTION, MODIFICATION, DISTRIBUTION, PUBLIC
# PERFORMANCE, OR PUBLIC DISPLAY OF OR THROUGH USE OF THIS SOURCE CODE WITHOUT
# THE EXPRESS WRITTEN CONSENT OF APPLIED BRAIN RESEARCH IS STRICTLY PROHIBITED,
# AND IN VIOLATION OF APPLICABLE LAWS AND INTERNATIONAL TREATIES. THE RECEIPT
# OR POSSESSION OF THIS SOURCE CODE AND/OR RELATED INFORMATION DOES NOT CONVEY
# OR IMPLY ANY RIGHTS TO REPRODUCE, DISCLOSE OR DISTRIBUTE ITS CONTENTS, OR TO
# MANUFACTURE, USE, OR SELL ANYTHING THAT IT MAY DESCRIBE, IN WHOLE OR IN PART.

#
# This file has been auto-generated by `abr-bindgen`. Do not modify!
#

"""
Python wrapper around the ABR SDK C ABI.

The C ABI is the interface between the ABR shared libraries and the SDK
frontends. This binding has been automatically generated from the C ABI
header files. Users should not use the functionality from this header directly.

Author: Andreas Stöckel (Applied Brain Research)
"""

# Do not complain about the docstrings for now.
# ruff: noqa: D202, D205, D401

import ctypes
import enum
from collections.abc import Callable
from pathlib import Path
from typing import Any, ClassVar, Union

from abr_sdk.exceptions import AbrSdkError

###############################################################################
# Macros                                                                      #
###############################################################################

ABR_ABI_MAJOR = 3
"""Major supported ABI version. Use for shared library compatibility checks."""

ABR_ABI_MINOR = 0
"""Minor supported ABI version. Use for shared library compatibility checks."""

###############################################################################
# Enumerations                                                                #
###############################################################################


class Status(enum.IntEnum):
    """
    Possible status codes returned by the various ABR functions.
    """

    OK = 0
    """
    The operation was successful.
    """

    ERR_INVALID_ARGS = -1
    """
    The API was used incorrectly; values may be out-of-range, or the given
    handles may point at the wrong object type.
    """

    ERR_INVALID_CONFIG = -2
    """
    Error in the `cfg` dictionary passed to `abr_app_create`.

    Either a required key is missing, a key has an incorrect value, or a given
    key is unknown. See the log output for more information.
    """

    ERR_TIMEOUT = -3
    """
    The specified timeout expired while waiting for events.
    """

    ERR_INTERRUPT = -4
    """
    The process received a signal from the operating system while waiting for
    events, or a user called abr_evset_interrupt() from another thread.
    """

    ERR_PLATFORM_UNSUPPORTED = -5
    """
    The current platform is not supported by this ABR library. You may be
    attempting to load a ABR library that was compiled for a specific
    accelerator, but that accelerator is not available.
    """

    ERR_BUSY = -6
    """
    Another ABR library instance (may be in a separate process) is already
    using the current accelerator.
    """

    ERR_SYSTEM = -7
    """
    A system call failed. See the log for more information.
    """

    ERR_PERMISSION = -8
    """
    There was a permission error while attempting to access a resource, such as
    a neural network accelerator or a file with model weights.
    """

    ERR_NOT_IMPLEMENTED = -9
    """
    This function is not implemented yet.
    """

    ERR_INCOMPATIBLE_APP = -10
    """
    The attempted operation is incompatible with this application.
    """

    ERR_INCOMPATIBLE_LIBRARY = -11
    """
    The shared library is incompatible with this version of the ABR SDK.
    """

    ERR_NOT_STATICALLY_LINKED = -12
    """
    Attempting to open the ABR SDK in "statically linked" mode, but the library
    has not been linked at compile time.
    """

    ERR_LICENSE = -13
    """
    The license check failed.

    See the log messages for information on what precisely caused this error
    and how and it can be solved.
    """


class LogLevel(enum.IntEnum):
    """
    Levels used for log messages.
    """

    DEFAULT = 0
    """
    Use the default log level.
    """

    TRACE = 5
    """
    Trace-level logging for detailed debugging.
    """

    DEBUG = 10
    """
    Debug-level logging for development purposes.
    """

    INFO = 20
    """
    Informational messages about normal operation.
    """

    WARNING = 30
    """
    Warning messages for potentially problematic situations.
    """

    ERROR = 40
    """
    Error messages for recoverable failures.
    """

    CRITICAL = 50
    """
    Critical messages for severe failures.
    """

    DISABLE = 0x7FFFFFFF
    """
    Disable all logging.
    """


class VariantType(enum.IntEnum):
    """
    Possible types for variant values.

    Variants are used for runtime-typed values in configuration and properties.
    """

    UNDEFINED = 0
    """
    The variant has no defined value.
    """

    NULL = 1
    """
    The variant represents a null value.
    """

    BOOLEAN = 2
    """
    The variant contains a boolean value.
    """

    UINT = 3
    """
    The variant contains an unsigned integer.
    """

    SINT = 4
    """
    The variant contains a signed integer.
    """

    PTR = 5
    """
    The variant contains a pointer.
    """

    STR = 6
    """
    The variant contains a string.
    """


class EventFlags(enum.IntEnum):
    """
    Possible flags for event creation. These can be combined via bitwise `or`.
    """

    NONE = 0
    """
    No special event flags set.
    """

    AUTO_DISABLE = 1
    """
    Automatically disables events that are triggered during a call to `poll` or
    while waiting for the platform event handle.

    This is useful if the calling code needs to wait for multiple events to be
    triggered before some action can be performed. Without auto-disabling,
    events must be manually disabled to avoid `poll` constantly returning,
    which complicates the code.
    """

    DISABLED = 2
    """
    Create the event in a "disabled" state.

    Using this flag avoids the event becoming triggered in between event
    creation and the call to `abr_event_disable()`.
    """


class AsrTextChunkType(enum.IntEnum):
    """
    Enumeration defining different ASR text chunk types.

    End-users may filter chunks depending on their latency and quality
    requirements.
    """

    NONE = 0
    """
    Not used in valid text chunks.

    Chunks with this type should be ignored.
    """

    CAUSAL = 1
    """
    The text was produced by the low-latency but less accurate "causal" branch
    of the model.
    """

    NONCAUSAL = 2
    """
    The text was produced by the higher latency but high-quality "non-causal"
    branch of the model.
    """

    POSTPROC = 3
    """
    The text was produced as the result of a post-processing operation, such as
    a language model or a punctuation model. At this level, the produced text
    has the highest quality, but also the highest inserted latency.
    """


###############################################################################
# Structures                                                                  #
###############################################################################


class VariantValue(ctypes.Union):
    """
    String value, valid when type is #ABR_VAR_STR.
    """

    _fields_ = (
        ("boolean", ctypes.c_bool),
        ("uint", ctypes.c_uint64),
        ("sint", ctypes.c_int64),
        ("ptr", ctypes.c_void_p),
        ("str", ctypes.c_char_p),
    )


class Variant(ctypes.Structure):
    """
    The actual value. The active union member is determined by @ref type.
    """

    _fields_ = (
        ("type", ctypes.c_uint8),
        ("value", VariantValue),
    )


class Config(ctypes.Structure):
    """
    The configuration value.
    """

    _fields_ = (
        ("key", ctypes.c_char_p),
        ("value", Variant),
    )


class AsrTextChunk(ctypes.Structure):
    """
    Small buffer containing the actual character data.
    """

    _fields_ = (
        ("type", ctypes.c_uint8),
        ("pad0_", ctypes.c_uint8),
        ("replace_byte_offs_begin", ctypes.c_int16),
        ("replace_byte_offs_end", ctypes.c_int16),
        ("n_bytes", ctypes.c_uint8),
        ("pad1_", ctypes.c_uint8),
        ("data", ctypes.c_uint8 * 32),
    )


###############################################################################
# Callback function type                                                      #
###############################################################################

LogCallback = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.c_int32, ctypes.c_char_p)
"""Function type used to connect the ABR SDK logger to the Python log system."""

###############################################################################
# Exception handling                                                          #
###############################################################################


class AbrSdkCAbiError(AbrSdkError):
    """Exception thrown if a C function returns with an error code."""

    def __init__(self, status: int | Status):
        self._status = Status(status)
        super().__init__(
            f"ABR SDK returned with error code {self._status.value} "
            f"({self._status.name})"
        )

    @property
    def status(self) -> Status:
        """Return the status code the exception was created with."""
        return self._status

    @staticmethod
    def check(status: int | Status) -> Status:
        """Throw a AbrSdkCAbiError if `status` indicates an error."""
        status = Status(status)
        if status.value < 0:
            raise AbrSdkCAbiError(status)
        return status


###############################################################################
# Function prototypes                                                         #
###############################################################################


def _resolve(
    cdll: ctypes.CDLL,
    name: str,
    argtypes: tuple[Any, ...],
    restype: Any,
    optional: bool = False,
) -> None:
    """
    Used internally to ensure that all required shared library exports exist and
    that they have the right type signature.
    """
    if not hasattr(cdll, name):
        if not optional:
            raise AbrSdkError(f"Cannot resolve symbol `{name}`")
        return

    fun = getattr(cdll, name)
    fun.restype = restype
    fun.argtypes = argtypes


def _annotate_types(cdll: ctypes.CDLL) -> None:
    """Resolve all optional and non-optional ABR SDK symbols."""

    _resolve(
        cdll,
        "abr_abi_version",
        (),
        ctypes.c_uint32,
    )
    _resolve(
        cdll,
        "abr_app_create",
        (
            ctypes.POINTER(ctypes.c_void_p),
            ctypes.POINTER(Config),
            ctypes.c_uint32,
            ctypes.c_void_p,
            ctypes.c_void_p,
        ),
        ctypes.c_int8,
    )
    _resolve(
        cdll,
        "abr_app_activate_license",
        (
            ctypes.c_void_p,
            ctypes.c_char_p,
        ),
        ctypes.c_int8,
    )
    _resolve(
        cdll,
        "abr_app_reset",
        (ctypes.c_void_p,),
        ctypes.c_int8,
    )
    _resolve(
        cdll,
        "abr_app_free",
        (ctypes.c_void_p,),
        None,
    )
    _resolve(
        cdll,
        "abr_app_get_nn_count",
        (ctypes.c_void_p,),
        ctypes.c_uint32,
    )
    _resolve(
        cdll,
        "abr_app_get_nn",
        (
            ctypes.c_void_p,
            ctypes.c_uint32,
        ),
        ctypes.c_void_p,
    )
    _resolve(
        cdll,
        "abr_get_parent",
        (ctypes.c_void_p,),
        ctypes.c_void_p,
    )
    _resolve(
        cdll,
        "abr_get_property_count",
        (ctypes.c_void_p,),
        ctypes.c_uint32,
    )
    _resolve(
        cdll,
        "abr_get_property_name",
        (
            ctypes.c_void_p,
            ctypes.c_uint32,
        ),
        ctypes.c_char_p,
    )
    _resolve(
        cdll,
        "abr_get_property_value_by_idx",
        (
            ctypes.c_void_p,
            ctypes.c_uint32,
        ),
        Variant,
    )
    _resolve(
        cdll,
        "abr_get_property_value_by_name",
        (
            ctypes.c_void_p,
            ctypes.c_char_p,
        ),
        Variant,
    )
    _resolve(
        cdll,
        "abr_nn_get_buffer_count",
        (ctypes.c_void_p,),
        ctypes.c_uint32,
    )
    _resolve(
        cdll,
        "abr_nn_get_buffer",
        (
            ctypes.c_void_p,
            ctypes.c_uint32,
        ),
        ctypes.c_void_p,
    )
    _resolve(
        cdll,
        "abr_nn_is_idle",
        (ctypes.c_void_p,),
        ctypes.c_bool,
    )
    _resolve(
        cdll,
        "abr_buf_get_size",
        (ctypes.c_void_p,),
        ctypes.c_uint32,
    )
    _resolve(
        cdll,
        "abr_buf_get_level",
        (ctypes.c_void_p,),
        ctypes.c_uint32,
    )
    _resolve(
        cdll,
        "abr_buf_push",
        (
            ctypes.c_void_p,
            ctypes.POINTER(ctypes.c_uint8),
            ctypes.c_uint32,
        ),
        ctypes.c_int32,
    )
    _resolve(
        cdll,
        "abr_buf_pull",
        (
            ctypes.c_void_p,
            ctypes.POINTER(ctypes.c_uint8),
            ctypes.c_uint32,
        ),
        ctypes.c_int32,
    )
    _resolve(
        cdll,
        "abr_buf_clear",
        (ctypes.c_void_p,),
        None,
    )
    _resolve(
        cdll,
        "abr_evset_create",
        (ctypes.c_void_p,),
        ctypes.c_void_p,
    )
    _resolve(
        cdll,
        "abr_evset_get_platform_handle",
        (ctypes.c_void_p,),
        ctypes.c_int64,
    )
    _resolve(
        cdll,
        "abr_evset_poll",
        (
            ctypes.c_void_p,
            ctypes.c_int32,
        ),
        ctypes.c_int8,
    )
    _resolve(
        cdll,
        "abr_evset_interrupt",
        (ctypes.c_void_p,),
        None,
    )
    _resolve(
        cdll,
        "abr_evset_free",
        (ctypes.c_void_p,),
        None,
    )
    _resolve(
        cdll,
        "abr_event_create_buf_level_event",
        (
            ctypes.c_void_p,
            ctypes.c_void_p,
            ctypes.c_uint32,
            ctypes.c_uint8,
        ),
        ctypes.c_void_p,
    )
    _resolve(
        cdll,
        "abr_event_create_nn_idle_event",
        (
            ctypes.c_void_p,
            ctypes.c_void_p,
            ctypes.c_uint8,
        ),
        ctypes.c_void_p,
    )
    _resolve(
        cdll,
        "abr_event_create_app_idle_event",
        (
            ctypes.c_void_p,
            ctypes.c_uint8,
        ),
        ctypes.c_void_p,
    )
    _resolve(
        cdll,
        "abr_event_free",
        (ctypes.c_void_p,),
        None,
    )
    _resolve(
        cdll,
        "abr_event_is_triggered",
        (ctypes.c_void_p,),
        ctypes.c_bool,
    )
    _resolve(
        cdll,
        "abr_event_is_enabled",
        (ctypes.c_void_p,),
        ctypes.c_bool,
    )
    _resolve(
        cdll,
        "abr_event_enable",
        (ctypes.c_void_p,),
        None,
    )
    _resolve(
        cdll,
        "abr_event_disable",
        (ctypes.c_void_p,),
        None,
    )
    _resolve(
        cdll,
        "abr_asr_available",
        (ctypes.c_void_p,),
        ctypes.c_bool,
        optional=True,
    )
    _resolve(
        cdll,
        "abr_asr_get_input_buffer",
        (ctypes.c_void_p,),
        ctypes.c_void_p,
        optional=True,
    )
    _resolve(
        cdll,
        "abr_asr_get_text_chunk_output_buffer",
        (ctypes.c_void_p,),
        ctypes.c_void_p,
        optional=True,
    )
    _resolve(
        cdll,
        "abr_asr_flush",
        (ctypes.c_void_p,),
        None,
        optional=True,
    )
    _resolve(
        cdll,
        "abr_tts_available",
        (ctypes.c_void_p,),
        ctypes.c_bool,
        optional=True,
    )
    _resolve(
        cdll,
        "abr_tts_get_text_input_buffer",
        (ctypes.c_void_p,),
        ctypes.c_void_p,
        optional=True,
    )
    _resolve(
        cdll,
        "abr_tts_get_pcm_output_buffer",
        (ctypes.c_void_p,),
        ctypes.c_void_p,
        optional=True,
    )


class CAbi:
    """Typed wrapper around a ABR C SDK library."""

    CDLLCache: ClassVar[dict[str, ctypes.CDLL]] = {}

    def __init__(self, library_path: str | Path):
        """Attempts to open the shared library at `library_path`."""

        if library_path in CAbi.CDLLCache:
            self._cdll = CAbi.CDLLCache[library_path]
        else:
            self._cdll = ctypes.CDLL(library_path)
            CAbi.CDLLCache[library_path] = self._cdll

        _annotate_types(self._cdll)

    def abr_abi_version(
        self,
    ) -> int:
        """
        @short Returns an identifier describing the ABI version.

        The returned integer is structured as follows:

        - Bits 16-31: Major version (incompatible ABIs)

        - Bits 0-15: Minor version (new features, back and forward-compatible)

        A special case is major version zero used for in-development releases.
        Here even minor releases are incompatible with each other.

        @return The ABI version as a 32-bit unsigned integer.
        """

        return int(self._cdll.abr_abi_version())

    def abr_app_create(
        self,
        app_p: "ctypes._Pointer[ctypes.c_void_p]",
        cfg: "ctypes._Pointer[Config]",
        n_cfg: ctypes.c_uint32 | int,
        log_cb: Callable[[ctypes.c_void_p, ctypes.c_int32, ctypes.c_char_p], None]
        | None,
        log_cb_user_data: ctypes.c_void_p | None,
    ) -> Status:
        """
        @short Creates and initializes a new time-series application (ABR)
        instance.

        Applications may create an arbitrary number of ABR instances, as long
        as the underlying accelerator supports this, and there are enough
        resources (i.e., memory) left.

        Every ABR instance is optionally linked to a logger; this is used to
        capture log messages from the ABR modules.

        @param app_p Pointer to the variable where the newly created ABR handle
        will be stored. This will be set to @c NULL if initialization fails.

        @param cfg Pointer to an array of configuration options. May be @c NULL
        if no additional configuration is needed. Recognized keys depend on the
        loaded application; the library picks the default for any key the
        caller omits. Application-specific keys are namespaced by the
        application name (e.g. ASR exposes "asr_*").

        Application-agnostic keys:

        - "min_log_level" (#ABR_VAR_SINT, see #abr_log_level): minimum severity
        threshold passed to the logger. Defaults to #ABR_LOG_DEFAULT.

        - "resources_dir" (#ABR_VAR_STR): filesystem directory the loaded
        library reads model weights from. Defaults to the directory containing
        the loaded shared library.

        - "license_dir" (#ABR_VAR_STR): filesystem directory in which license
        data is stored.

        ASR-specific keys:

        - "asr_mode" (#ABR_VAR_STR): which decoder branch is surfaced. One of:

        - "fast": causal decoder (lower-quality, sooner output).

        - "accurate": noncausal decoder (higher-quality, lookahead latency).
        Defaults to "accurate".

        @param n_cfg Number of configuration options in the @p cfg array.

        @param log_cb Pointer to the log callback function. Passing @c NULL
        disables logging.

        @param log_cb_user_data Arbitrary pointer passed as the first argument
        to

        @p log_cb. Useful for object-oriented patterns where @p log_cb is a
        member function and @p log_cb_user_data is a class instance.

        @return One of the following status codes:

        - #ABR_OK: A valid pointer has been written to @p abr_p, and the
        application is ready to use.

        - #ABR_ERR_LICENSE: A valid pointer has been written to @p abr_p, but
        license activation is required to actually use any function other than
        the license activation function. See the log for more details.

        - #ABR_ERR_PLATFORM_UNSUPPORTED: This application library is not
        supported on this machine. You may be attempting to open an application
        library that uses a hardware accelerator that is not available on your
        machine.

        - #ABR_ERR_BUSY: The targeted accelerator is already busy executing
        another application.

        - #ABR_ERR_SYSTEM: A system call returned with an error.

        Depending on the error code, additional information may have been
        logged.
        """

        return AbrSdkCAbiError.check(
            self._cdll.abr_app_create(
                app_p,
                cfg,
                n_cfg,
                log_cb,
                log_cb_user_data,
            )
        )

    def abr_app_activate_license(
        self,
        app: ctypes.c_void_p | None,
        envelope: ctypes.c_char_p | bytes | bytearray,
    ) -> Status:
        """
        Given a response from the server, activates a license for this
        application.

        This will use the configuration options and the logger passed to
        `abr_app_create`.

        @param app is an application instance previously create by
        `abr_app_create`. The `app` pointer written by `abr_app_create` is
        valid even if `abr_app_create` returned `ABR_ERR_LICENSE`.

        @param envelope is a pointer at a zero-terminated string containing the
        signed license envelope.

        @return One of the following status codes:

        - #ABR_OK: The application has been activated.

        - #ABR_ERR_INVALID_ARGS: The app or envelope pointers are NULL.

        - #ABR_ERR_LICENSE: The license could not be validated. See the log for
        more details.
        """

        return AbrSdkCAbiError.check(
            self._cdll.abr_app_activate_license(
                app,
                envelope,
            )
        )

    def abr_app_reset(
        self,
        app: ctypes.c_void_p | None,
    ) -> Status:
        """
        @short Resets the entire application to its initial state.

        Resets the application without freeing/re-allocating resources and
        without invalidating handles.

        @param app Pointer to the ABR instance to reset.

        @return #ABR_OK on success, or a negative error code on failure.
        """

        return AbrSdkCAbiError.check(
            self._cdll.abr_app_reset(
                app,
            )
        )

    def abr_app_free(
        self,
        app: ctypes.c_void_p | None,
    ) -> None:
        """
        @short Frees the ABR instance and all resources held by it.

        Note that this invalidates all other handles that (directly or
        indirectly) have this application instance as a parent.

        This function does nothing if @p app is @c NULL; i.e., it is safe to
        call abr_app_free() independent of whether the library has been
        initialized correctly or not.

        @param app Pointer to the ABR instance to free, or @c NULL.
        """

        self._cdll.abr_app_free(app)

    def abr_app_get_nn_count(
        self,
        app: ctypes.c_void_p | None,
    ) -> int:
        """
        @short Returns the number of neural networks in the application.

        @param app Pointer to the ABR instance.

        @return The number of neural networks, or zero if @p app is @c NULL.
        """

        return int(self._cdll.abr_app_get_nn_count(app))

    def abr_app_get_nn(
        self,
        app: ctypes.c_void_p | None,
        idx: ctypes.c_uint32 | int,
    ) -> ctypes.c_void_p:
        """
        @short Fetches the neural network with the given index from the ABR
        instance.

        Calling this function multiple times with the same index will always
        return the same neural network object. There is no need to free these
        objects after use.

        @param app Pointer to the ABR instance.

        @param idx Zero-based index of the neural network to retrieve.

        @return A pointer to the neural network, or @c NULL if @p app is @c
        NULL or

        @p idx is out of range.
        """

        return ctypes.c_void_p(self._cdll.abr_app_get_nn(app, idx))

    def abr_get_parent(
        self,
        obj: ctypes.c_void_p | None,
    ) -> ctypes.c_void_p:
        """
        @short Returns the parent object of the specified object.

        @param obj Pointer to any ABR object; this may be a #abr_app_t, a
        #abr_nn_t, etc. May be @c NULL.

        @return The parent object of the given object, or @c NULL if the object
        has no known parent object.
        """

        return ctypes.c_void_p(self._cdll.abr_get_parent(obj))

    def abr_get_property_count(
        self,
        obj: ctypes.c_void_p | None,
    ) -> int:
        """
        @short Returns the number of properties attached to the given object.

        Every ABR object may have a series of runtime-defined properties
        attached. These properties are used for values that do not need to be
        accessed very often. Using a generic interface avoids having to add new
        functions to the C ABI every time a new property is exported.

        Passing @c NULL provides information about the application library
        itself.

        @param obj Pointer to a ABR object; this may be a #abr_app_t, a
        #abr_nn_t, a #abr_buf_t, etc. Passing @c NULL provides access to the
        global "meta" scope.

        @return The number of properties.
        """

        return int(self._cdll.abr_get_property_count(obj))

    def abr_get_property_name(
        self,
        obj: ctypes.c_void_p | None,
        idx: ctypes.c_uint32 | int,
    ) -> bytes | None:
        """
        @short Returns the property name by index.

        @param obj Pointer to a ABR object, or @c NULL for the global "meta"
        scope.

        @param idx Zero-based index of the property.

        @return The property name, or @c NULL if the index is out of range.
        """

        return self._cdll.abr_get_property_name(obj, idx)

    def abr_get_property_value_by_idx(
        self,
        obj: ctypes.c_void_p | None,
        idx: ctypes.c_uint32 | int,
    ) -> Variant:
        """
        @short Returns a property value by index.

        @param obj Pointer to a ABR object, or @c NULL for the global "meta"
        scope.

        @param idx Zero-based index of the property.

        @return The property value, or an "undefined" variant if the index is
        out of range or the object is not known.
        """

        return self._cdll.abr_get_property_value_by_idx(obj, idx)

    def abr_get_property_value_by_name(
        self,
        obj: ctypes.c_void_p | None,
        key: ctypes.c_char_p | bytes | bytearray,
    ) -> Variant:
        """
        @short Returns a property value by name.

        @param obj Pointer to a ABR object, or @c NULL for the global "meta"
        scope.

        @param key The property name to look up. Keys are case-sensitive.

        @return The property value, or an "undefined" variant if the name is
        not found or the object is not known.
        """

        return self._cdll.abr_get_property_value_by_name(obj, key)

    def abr_nn_get_buffer_count(
        self,
        nn: ctypes.c_void_p | None,
    ) -> int:
        """
        @short Returns the number of I/O buffers available in this neural
        network.

        @param nn Pointer to the neural network.

        @return The number of buffers, or zero if @p nn is @c NULL or @p nn
        does not point at a valid #abr_nn_t object.
        """

        return int(self._cdll.abr_nn_get_buffer_count(nn))

    def abr_nn_get_buffer(
        self,
        nn: ctypes.c_void_p | None,
        idx: ctypes.c_uint32 | int,
    ) -> ctypes.c_void_p:
        """
        @short Fetches the i-th buffer from the neural network.

        The total number of I/O buffers in the neural network may be obtained
        using abr_nn_get_buffer_count().

        Calling this function multiple times will return the same buffer
        object. There is no need to free buffer objects after use.

        @param nn Pointer to the neural network.

        @param idx Zero-based index of the buffer to retrieve.

        @return Pointer to the buffer, or @c NULL if @p nn is @c NULL, @p idx
        is out of range, or @p nn is not pointing at a valid #abr_nn_t object.
        """

        return ctypes.c_void_p(self._cdll.abr_nn_get_buffer(nn, idx))

    def abr_nn_is_idle(
        self,
        nn: ctypes.c_void_p | None,
    ) -> bool:
        """
        @short Returns @c true if this neural network is currently idle.

        @param nn Pointer to the neural network.

        @return @c true if the neural network is idle, @c false if the network
        is active or if @p nn is not pointing at a valid neural network object.
        """

        return bool(self._cdll.abr_nn_is_idle(nn))

    def abr_buf_get_size(
        self,
        buf: ctypes.c_void_p | None,
    ) -> int:
        """
        @short Returns the total buffer capacity in bytes.

        @param buf Pointer to the buffer.

        @return The buffer capacity in bytes, or zero if @p buf is @c NULL.
        """

        return int(self._cdll.abr_buf_get_size(buf))

    def abr_buf_get_level(
        self,
        buf: ctypes.c_void_p | None,
    ) -> int:
        """
        @short Returns the current buffer fill level in bytes.

        @param buf Pointer to the buffer.

        @return The number of bytes currently in the buffer, or zero if @p buf
        is

        @c NULL.
        """

        return int(self._cdll.abr_buf_get_level(buf))

    def abr_buf_push(
        self,
        buf: ctypes.c_void_p | None,
        data: Union["ctypes._Pointer[ctypes.c_uint8]", bytes, bytearray],
        n_bytes: ctypes.c_uint32 | int,
    ) -> int:
        """
        @short Pushes (writes) data onto a buffer.

        Does nothing if the buffer is connected to a neural network output.

        @param buf Pointer to the buffer.

        @param data Pointer to the data to push.

        @param n_bytes Number of bytes to push.

        @return The number of bytes actually pushed onto the buffer, or a
        negative error code (compatible with #abr_status_t) on failure.
        """

        return int(self._cdll.abr_buf_push(buf, data, n_bytes))

    def abr_buf_pull(
        self,
        buf: ctypes.c_void_p | None,
        data: Union["ctypes._Pointer[ctypes.c_uint8]", bytes, bytearray],
        n_bytes: ctypes.c_uint32 | int,
    ) -> int:
        """
        @short Pulls (reads) data from a buffer.

        Does nothing if the buffer is connected to a neural network input.

        @param buf Pointer to the buffer.

        @param data Pointer to the buffer where pulled data will be stored.

        @param n_bytes Maximum number of bytes to pull.

        @return The number of bytes actually pulled from the buffer, or a
        negative error code (compatible with #abr_status_t) on failure.
        """

        return int(self._cdll.abr_buf_pull(buf, data, n_bytes))

    def abr_buf_clear(
        self,
        buf: ctypes.c_void_p | None,
    ) -> None:
        """
        @short Clears the given buffer object.

        Removes all data from the buffer, resetting the fill level to zero.

        @param buf Pointer to the buffer to clear.
        """

        self._cdll.abr_buf_clear(buf)

    def abr_evset_create(
        self,
        app: ctypes.c_void_p | None,
    ) -> ctypes.c_void_p:
        """
        @short Create a new event set connected to the given ABR instance.

        The event set (short "evset") may be used by a single user thread to
        wait for certain events to happen within a neural network.

        @param app Pointer to the ABR instance.

        @return Pointer to the newly created event set, or @c NULL on failure.
        """

        return ctypes.c_void_p(self._cdll.abr_evset_create(app))

    def abr_evset_get_platform_handle(
        self,
        evset: ctypes.c_void_p | None,
    ) -> int:
        """
        @short Return the platform-specific event handle.

        The event handle may be used to yield to the operating system until a
        buffer event (configured through the buffer interface) happens.

        On POSIX-like systems, the returned handle is a file descriptor of a

        @c socketpair() or a compatible mechanism such as @c eventfd() on
        Linux. An event results in eight bytes becoming readable from the file
        descriptor. The user must read those eight bytes to confirm the event.

        The file descriptor is meant to be used in conjunction with @c
        poll()-like event loops typically used by event-runtimes, such as
        Python @c async or

        @c libuv (NodeJS/JavaScript), or Boost ASIO (C++).

        The exact semantics of the returned handle on Windows platforms is yet
        to be determined.

        @param evset Pointer to the event set.

        @return The platform-specific handle, or a negative value on error.
        """

        return int(self._cdll.abr_evset_get_platform_handle(evset))

    def abr_evset_poll(
        self,
        evset: ctypes.c_void_p | None,
        timeout_ms: ctypes.c_int32 | int,
    ) -> Status:
        """
        @short Block the current thread until an event is triggered or timeout.

        This function returns once at least one event in the event set is in
        the "enabled" and "triggered" state.

        Events created with the #ABR_EVENT_FLAGS_AUTO_DISABLE flag are disabled
        if they cause abr_evset_poll() to return. Users must explicitly enable
        events again once they are interested in that event again. This
        simplifies usage patterns where users need to wait for multiple events
        to become triggered before something can happen.

        Under the hood, this function uses the event platform handle to yield
        to the operating system. This function may be used if the runtime does
        not provide an easy way to integrate an event handle into the main
        asynchronous I/O loop.

        @param evset Pointer to the event set to poll.

        @param timeout_ms Timeout in milliseconds. A positive value indicates
        the maximum time to wait. A value of zero returns immediately with
        #ABR_OK if an event is ready, or #ABR_ERR_TIMEOUT otherwise. A negative
        value denotes an infinite timeout.

        @return One of the following status codes:

        - #ABR_OK: At least one event is triggered. Use
        abr_event_is_triggered() to determine which event.

        - #ABR_ERR_TIMEOUT: The timeout expired.

        - #ABR_ERR_INTERRUPT: The process received a signal/interrupt while
        waiting or `abr_evset_interrupt()` was called. It is safe to call
        abr_evset_poll() again in this case.
        """

        return AbrSdkCAbiError.check(
            self._cdll.abr_evset_poll(
                evset,
                timeout_ms,
            )
        )

    def abr_evset_interrupt(
        self,
        evset: ctypes.c_void_p | None,
    ) -> None:
        """
        Interrupt a call to `abr_evset_poll` or a thread waiting on the event
        set platform handle.

        The `abr_evset_poll()` function will return with #ABR_ERR_INTERRUPT if
        this function is called and no event has been triggered before the
        thread calling abr_evset_poll() resumes.

        @param evset Event set that should be interrupted.
        """

        self._cdll.abr_evset_interrupt(evset)

    def abr_evset_free(
        self,
        evset: ctypes.c_void_p | None,
    ) -> None:
        """
        @short Free a previously created event set.

        Frees the event set and all events connected to it.

        @param evset Pointer to the event set to free, or @c NULL.
        """

        self._cdll.abr_evset_free(evset)

    def abr_event_create_buf_level_event(
        self,
        evset: ctypes.c_void_p | None,
        buf: ctypes.c_void_p | None,
        threshold: ctypes.c_uint32 | int,
        flags: ctypes.c_uint8 | int,
    ) -> ctypes.c_void_p:
        """
        @short Register a buffer level event for the given buffer.

        The I/O event is triggered if there are @p threshold bytes available
        for reading from or writing to the buffer.

        @param evset Pointer to the event set.

        @param buf Pointer to the buffer to monitor.

        @param threshold Number of bytes that must be available to trigger the
        event.

        @param flags Bitwise combination of `abr_event_flags_t` enum values
        that influence how the event behaves.

        @return Pointer to the newly created event, or @c NULL on failure.
        """

        return ctypes.c_void_p(
            self._cdll.abr_event_create_buf_level_event(evset, buf, threshold, flags)
        )

    def abr_event_create_nn_idle_event(
        self,
        evset: ctypes.c_void_p | None,
        nn: ctypes.c_void_p | None,
        flags: ctypes.c_uint8 | int,
    ) -> ctypes.c_void_p:
        """
        @short Register an "idle" event for the given neural network.

        This event is triggered as long as the neural network cannot make any
        progress due to a lack of input data.

        This event is not triggered if the neural network still has data that
        could be emitted, but it cannot emit that data because there is not
        enough space in the output buffer.

        Note that there may still be data in the neural network output buffers
        once this event triggers; "idle" just means that no more data will be
        written to the neural network output buffers as long as no new data is
        being fed in.

        @param evset Pointer to the event set.

        @param nn Pointer to the neural network to monitor.

        @param flags Bitwise combination of `abr_event_flags_t` enum values
        that influence how the event behaves.

        @return Pointer to the newly created event, or @c NULL on failure.
        """

        return ctypes.c_void_p(
            self._cdll.abr_event_create_nn_idle_event(evset, nn, flags)
        )

    def abr_event_create_app_idle_event(
        self,
        evset: ctypes.c_void_p | None,
        flags: ctypes.c_uint8 | int,
    ) -> ctypes.c_void_p:
        """
        @short Create an application-level idle event.

        This event is triggered whenever the following conditions are met:

        - All neural networks in the application are idle.

        - All pre- and post-processing processes are idle.

        As with the neural network idle event, "idle" means that the
        corresponding component cannot make any progress without more input
        being fed into the pipeline. If a component could still emit data, but
        is blocked by doing so because of full output buffers, then this event
        is not triggered.

        Note that there may still be data in the output buffers once this event
        triggers; "idle" just means that no more data will be written to the
        application output buffers as long as no new data is being fed in.

        This event marks the end of the "flush" process. Once the caller
        requests a flush (e.g. #abr_asr_flush), the application drains its
        pre/NN/post pipeline, then this event will fire:

        1. Create the event with @c ABR_EVENT_FLAGS_AUTO_DISABLE and

        @c ABR_EVENT_FLAGS_DISABLED. 2. Call the application's flush function.
        3. Enable the event. 4. Poll on the event set; when this event
        triggers, the application has finished flushing and the caller can read
        the final output.

        @param evset Pointer to the event set; the parent application of the
        event set determines which application's idle state is monitored.

        @param flags Bitwise combination of `abr_event_flags_t` values
        controlling the event's behavior.

        @return An `abr_event_t` instance, or @c NULL if @p evset is @c NULL.
        """

        return ctypes.c_void_p(self._cdll.abr_event_create_app_idle_event(evset, flags))

    def abr_event_free(
        self,
        event: ctypes.c_void_p | None,
    ) -> None:
        """
        @short Free a previously created event.

        This function does nothing if @p event is @c NULL or does not point at
        a valid event.

        @param event Pointer to the event to free, or @c NULL.
        """

        self._cdll.abr_event_free(event)

    def abr_event_is_triggered(
        self,
        event: ctypes.c_void_p | None,
    ) -> bool:
        """
        @short Return @c true if the event has been triggered.

        Returns whether the event has reached its trigger condition. This
        function is independent of the event's enabled/disabled status.

        @param event Pointer to the event to check.

        @return @c true if the event is in the triggered state, @c false
        otherwise or if @p event is @c NULL.
        """

        return bool(self._cdll.abr_event_is_triggered(event))

    def abr_event_is_enabled(
        self,
        event: ctypes.c_void_p | None,
    ) -> bool:
        """
        @short Return @c true if the event is currently enabled.

        Only enabled events can cause the underlying event set to wake up,
        i.e., cause the platform handle to become readable or abr_evset_poll()
        to return. Note that events can only be disabled if the event was
        created with the #ABR_EVENT_FLAGS_AUTO_DISABLE flag, or if it was
        manually disabled by calling abr_event_disable().

        To re-enable an event, call abr_event_enable(). To disable an event
        call abr_event_disable().

        @param event Pointer to the event to check.

        @return @c true if the event is enabled, @c false otherwise or if

        @p event is @c NULL.
        """

        return bool(self._cdll.abr_event_is_enabled(event))

    def abr_event_enable(
        self,
        event: ctypes.c_void_p | None,
    ) -> None:
        """
        @short (Re-)enable an event.

        Ensures that the given event can cause `poll` to return, or, when using
        the platform handle, the handle to become readable.

        @param event Pointer to the event to enable. Does nothing if the
        pointer is `NULL` or the pointer does not point at an event object.
        """

        self._cdll.abr_event_enable(event)

    def abr_event_disable(
        self,
        event: ctypes.c_void_p | None,
    ) -> None:
        """
        @short Disable an event.

        After having been disabled, the event cannot cause `poll` to return,
        or, when using the platform handle, the handle to become readable.

        @param event Pointer to the event to disable. Does nothing if the
        pointer is `NULL` or the pointer does not point at an event object.
        """

        self._cdll.abr_event_disable(event)

    def abr_asr_available(
        self,
        app: ctypes.c_void_p | None,
    ) -> bool:
        """
        Return @c true if the given application supports the ASR interface.

        @param app Pointer to the ABR application instance to check.

        @return @c true if the ABR instance supports ASR, @c false otherwise or
        if

        @p asr is @c NULL.
        """

        # This function is part of an API extension. Return a falsy instance
        # of the return type in case the function symbol does not exist.
        if not hasattr(self._cdll, "abr_asr_available"):
            return False

        return bool(self._cdll.abr_asr_available(app))

    def abr_asr_get_input_buffer(
        self,
        asr: ctypes.c_void_p | None,
    ) -> ctypes.c_void_p:
        """
        Return a handle to the ASR input buffer.

        Data meant for ASR processing must be placed in this buffer. The SDK
        automatically orchestrates the appropriate pre-processing steps and
        feeds the data into the neural network. The content the buffer expects
        depends on the loaded application: PCM audio (16-bit signed integers,
        typically 16 kHz) for audio-input variants, or raw UTF-8 text for text-
        input variants.

        @param asr Pointer to the ASR application.

        @return A pointer to the input buffer, or @c NULL if @p asr is @c NULL
        or the ABR instance does not support ASR.
        """

        # This function is part of an API extension. Return a falsy instance
        # of the return type in case the function symbol does not exist.
        if not hasattr(self._cdll, "abr_asr_get_input_buffer"):
            return ctypes.c_void_p()

        return ctypes.c_void_p(self._cdll.abr_asr_get_input_buffer(asr))

    def abr_asr_get_text_chunk_output_buffer(
        self,
        asr: ctypes.c_void_p | None,
    ) -> ctypes.c_void_p:
        """
        Return a handle to the ASR text chunk output buffer.

        The output of the ASR application is a stream of "text chunks". These
        are small pieces of text along with additional metadata.

        The buffer emits #abr_asr_text_chunk_t structures containing the
        recognized text. Only chunks belonging to the decoder branch selected
        by the "asr_mode" config key are delivered (see `abr_app_create` for
        the valid values and the library default).

        @param asr Pointer to the ASR application.

        @return A pointer to the output buffer, or @c NULL if @p asr is @c NULL
        or the @p asr instance does not support ASR.
        """

        # This function is part of an API extension. Return a falsy instance
        # of the return type in case the function symbol does not exist.
        if not hasattr(self._cdll, "abr_asr_get_text_chunk_output_buffer"):
            return ctypes.c_void_p()

        return ctypes.c_void_p(self._cdll.abr_asr_get_text_chunk_output_buffer(asr))

    def abr_asr_flush(
        self,
        asr: ctypes.c_void_p | None,
    ) -> None:
        """
        Flush the ASR pipeline.

        Call this function after the final audio data has been pushed to signal
        the end of the audio stream. This allows the ASR application to
        finalize any pending transcriptions. Wait for
        #abr_event_create_app_idle_event to fire to know when finalization has
        completed.

        This function cannot fail. If the ABR instance does not support ASR,
        then nothing happens.

        @param asr Pointer to the ASR application.
        """

        # This function is part of an API extension. Return a falsy instance
        # of the return type in case the function symbol does not exist.
        if not hasattr(self._cdll, "abr_asr_flush"):
            return

        self._cdll.abr_asr_flush(asr)

    def abr_tts_available(
        self,
        app: ctypes.c_void_p | None,
    ) -> bool:
        """
        Return @c true if the given application supports the TTS interface.

        The text-to-speech (TTS) interface is used for any application that
        takes text as an input, and produces audio as an output.

        @param app Pointer to the ABR application instance to check.

        @return @c true if the application supports TTS, @c false otherwise or
        if

        @p app is @c NULL.
        """

        # This function is part of an API extension. Return a falsy instance
        # of the return type in case the function symbol does not exist.
        if not hasattr(self._cdll, "abr_tts_available"):
            return False

        return bool(self._cdll.abr_tts_available(app))

    def abr_tts_get_text_input_buffer(
        self,
        app: ctypes.c_void_p | None,
    ) -> ctypes.c_void_p:
        """
        Return a handle to the TTS text input buffer.

        The input to the TTS application is a UTF-8 encoded text stream with
        optional SSML tags.

        TTS is streaming: the system attempts to output speech for the given
        text as soon as possible. The TTS pipeline is guaranteed to be flushed
        whenever an "end of sentence" is detected.

        @param app Pointer to the ABR application.

        @return A pointer to the input buffer, or @c NULL if @p app is @c NULL
        or the

        @p app instance does not support TTS.
        """

        # This function is part of an API extension. Return a falsy instance
        # of the return type in case the function symbol does not exist.
        if not hasattr(self._cdll, "abr_tts_get_text_input_buffer"):
            return ctypes.c_void_p()

        return ctypes.c_void_p(self._cdll.abr_tts_get_text_input_buffer(app))

    def abr_tts_get_pcm_output_buffer(
        self,
        app: ctypes.c_void_p | None,
    ) -> ctypes.c_void_p:
        """
        Return a handle to the TTS PCM output buffer.

        Data in this buffer is a continuous signed 16-bit PCM audio stream.

        @param app Pointer to the ABR application.

        @return A pointer to the output buffer, or @c NULL if @p app is @c NULL
        or the @p app instance does not support TTS.
        """

        # This function is part of an API extension. Return a falsy instance
        # of the return type in case the function symbol does not exist.
        if not hasattr(self._cdll, "abr_tts_get_pcm_output_buffer"):
            return ctypes.c_void_p()

        return ctypes.c_void_p(self._cdll.abr_tts_get_pcm_output_buffer(app))
