import EventEmitter from "node:events";
import { AudioFormat } from "./audio-format.mjs";
import { AudioQuality } from "./audio-quality.mjs";
import type { NativePipeWireSession } from "./session.mjs";
import { type Latency, type StreamState } from "./stream.mjs";
import { type BufferConfig } from "./buffer-config.mjs";
export interface NativeAudioOutputStream {
    connect: (options?: {
        preferredFormats?: Array<number>;
        preferredRates?: Array<number>;
    }) => Promise<void>;
    disconnect: () => Promise<void>;
    get writableFrames(): number;
    get framesPerQuantum(): number;
    get bufferSize(): number;
    write: (data: ArrayBuffer) => void;
    waitForBuffer: () => Promise<number>;
    isFinished: () => Promise<void>;
    destroy: () => Promise<void>;
}
/**
 * Configuration options for creating audio output streams.
 * All options are optional with sensible defaults.
 *
 * @property name - Human-readable name displayed in PipeWire clients (default: "Node.js Audio")
 * @property rate - Sample rate in Hz (default: 48000)
 * @property channels - Number of audio channels (default: 2 for stereo)
 * @property role - Audio role hint for PipeWire routing (default: "Music")
 * @property quality - Quality preset that affects format negotiation (default: AudioQuality.Standard)
 * @property preferredFormats - Override format negotiation order
 * @property preferredRates - Override sample rate negotiation order
 * @property autoConnect - Whether to auto-connect after creation (default: false)
 * @property buffering - Buffer configuration for performance optimization
 * @property enableMonitoring - Enable performance monitoring and diagnostics (default: false)
 *
 * @example
 * ```typescript
 * const opts: AudioOutputStreamOpts = {
 *   name: "My Synthesizer",
 *   rate: 44100,
 *   channels: 2,
 *   quality: AudioQuality.High,
 *   role: "Music",
 *   enableMonitoring: true
 * };
 * ```
 */
export interface AudioOutputStreamOpts {
    name?: string;
    rate?: number;
    channels?: number;
    role?: "Movie" | "Music" | "Camera" | "Screen" | "Communication" | "Game" | "Notification" | "DSP" | "Production" | "Accessibility" | "Test";
    quality?: AudioQuality;
    preferredFormats?: Array<AudioFormat>;
    preferredRates?: Array<number>;
    autoConnect?: boolean;
    buffering?: BufferConfig;
    enableMonitoring?: boolean;
}
export interface AudioOutputStreamProps {
    volume: number;
    mute: boolean;
    monitorMute: boolean;
    softMute: boolean;
    channels: Array<{
        id: number;
        volume: number;
        mute: boolean;
        monitorVolume: number;
        softVolume: number;
    }>;
    params: Record<string, unknown>;
}
interface AudioEvents {
    propsChange: [AudioOutputStreamProps];
    formatChange: [{
        format: AudioFormat;
        channels: number;
        rate: number;
    }];
    latencyChange: [Latency];
    unknownParamChange: [number];
    stateChange: [StreamState];
    error: [Error];
    bufferAdjusted: [{
        oldSize: number;
        newSize: number;
        reason: string;
    }];
}
/**
 * Audio output stream for playing audio samples to PipeWire.
 * Streams are event emitters that provide real-time feedback about format changes,
 * latency updates, and connection state.
 *
 * @interface AudioOutputStream
 * @extends EventEmitter
 *
 * @example
 * ```typescript
 * const stream = await session.createAudioOutputStream({
 *   name: "Audio Generator",
 *   channels: 2,
 *   quality: AudioQuality.High
 * });
 *
 * await stream.connect();
 * await stream.write(audioSamples);
 * await stream.disconnect();
 * ```
 *
 * ## Events
 *
 * AudioOutputStream emits the following events:
 *
 * ### `formatChange`
 * Emitted when the stream's audio format is negotiated or changes.
 *
 * **Event payload:** `{ format: AudioFormat, channels: number, rate: number }`
 *
 * ```typescript
 * stream.on('formatChange', ({ format, channels, rate }) => {
 *   console.log(`Format: ${format.description}, ${channels}ch @ ${rate}Hz`);
 * });
 * ```
 *
 * ### `stateChange`
 * Emitted when the stream's connection state changes.
 *
 * **Event payload:** `StreamState` (string: "error", "unconnected", "connecting", "paused", "streaming")
 *
 * ```typescript
 * stream.on('stateChange', (state) => {
 *   console.log(`Stream state: ${state}`);
 * });
 * ```
 *
 * ### `latencyChange`
 * Emitted when the stream's latency information updates.
 *
 * **Event payload:** `{ min: number, max: number, default: number }` (all values in nanoseconds)
 *
 * ```typescript
 * stream.on('latencyChange', ({ min, max, default: def }) => {
 *   console.log(`Latency: ${def/1000000}ms (range: ${min/1000000}-${max/1000000}ms)`);
 * });
 * ```
 *
 * ### `propsChange`
 * Emitted when stream properties (volume, mute, etc.) change.
 *
 * **Event payload:** `AudioOutputStreamProps`
 *
 * ```typescript
 * stream.on('propsChange', (props) => {
 *   console.log(`Volume: ${props.volume}, Muted: ${props.mute}`);
 * });
 * ```
 *
 * ### `error`
 * Emitted when an error occurs during streaming.
 *
 * **Event payload:** `Error`
 *
 * ```typescript
 * stream.on('error', (error) => {
 *   console.error('Stream error:', error.message);
 * });
 * ```
 *
 * ### `unknownParamChange`
 * Emitted when PipeWire sends an unrecognized parameter change.
 *
 * **Event payload:** `number` (parameter ID)
 *
 * ```typescript
 * stream.on('unknownParamChange', (paramId) => {
 *   console.log(`Unknown parameter changed: ${paramId}`);
 * });
 * ```
 */
export interface AudioOutputStream extends EventEmitter<AudioEvents> {
    /**
     * Connect the stream to PipeWire audio system.
     * Triggers format negotiation and initializes audio processing.
     */
    connect: () => Promise<void>;
    /**
     * Disconnect the stream from PipeWire.
     * Stops audio processing and releases resources.
     */
    disconnect: () => Promise<void>;
    /**
     * Write audio samples to the stream.
     * Samples are JavaScript Numbers (-1.0 to 1.0) converted to negotiated format.
     */
    write: (samples: Iterable<number>) => Promise<void>;
    /**
     * Wait for all buffered audio to finish playing.
     * Useful for ensuring complete playback before cleanup.
     */
    isFinished: () => Promise<void>;
    /**
     * Dispose of the stream and release all resources.
     * Alternative to disconnect() for final cleanup.
     */
    dispose: () => Promise<void>;
    /**
     * Get the negotiated audio format after connection.
     * Available only after successful connect().
     */
    get format(): AudioFormat;
    /**
     * Get the negotiated number of audio channels.
     * Available only after successful connect().
     */
    get channels(): number;
    /**
     * Get the negotiated sample rate in Hz.
     * Available only after successful connect().
     */
    get rate(): number;
    /**
     * Get the buffer size in bytes.
     * This represents the total internal buffer size as negotiated
     * and adjusted by quantum alignment. If you specified a specific
     * number of bytes for buffering, the actual buffer may be different
     * due to quantum boundary alignment requirements.
     * Available only after successful connect().
     */
    get bufferSize(): number;
    /**
     * Check if the stream is currently connected to PipeWire.
     */
    get isConnected(): boolean;
    /**
     * Automatic resource cleanup for `await using` syntax.
     * Equivalent to calling dispose().
     */
    [Symbol.asyncDispose]: () => Promise<void>;
}
export interface TypedNumericArray {
    [index: number]: number;
    buffer: ArrayBuffer;
    subarray(offset: number, length: number): TypedNumericArray;
}
export type TypedNumericArrayCtor = new (size: number) => TypedNumericArray;
export declare class AudioOutputStreamImpl extends EventEmitter<AudioEvents> implements AudioOutputStream {
    #private;
    static create(session: NativePipeWireSession, opts?: AudioOutputStreamOpts): Promise<AudioOutputStream>;
    private constructor();
    connect(): Promise<void>;
    disconnect(): Promise<void>;
    get isConnected(): boolean;
    write(samples: Iterable<number>): Promise<void>;
    isFinished(): Promise<void>;
    get format(): AudioFormat;
    get channels(): number;
    get rate(): number;
    get bufferSize(): number;
    dispose(): Promise<void>;
    [Symbol.asyncDispose](): Promise<void>;
}
export {};
