/// <reference types="node" />
import { EventEmitter } from 'events';
import { DiagnosticError } from './errors';
import { AudioElement, SubsetRequired, TimeMeasurement } from './types';
export declare interface AudioOutputTest {
    /**
     * This event is emitted when the test ends.
     * @param event [[AudioOutputTest.Events.End]]
     * @param report A summary of the test.
     * @private
     */
    emit(event: AudioOutputTest.Events.End, report: AudioOutputTest.Report): boolean;
    /**
     * This event is emitted when the test encounters an error, fatal or not.
     * @param event [[AudioOutputTest.Events.Error]]
     * @param error An error that was encountered during the run time of the test.
     * @private
     */
    emit(event: AudioOutputTest.Events.Error, error: DiagnosticError): boolean;
    /**
     * This event is emitted by the test after succesfully starting, and emits
     * the volume of the audio source every [[AudioOutputTest.Options.volumeEventIntervalMs]]
     * milliseconds.
     * @param event [[AudioOutputTest.Events.Volume]]
     * @param value The volume of the audio source.
     * @private
     */
    emit(event: AudioOutputTest.Events.Volume, value: number): boolean;
    /**
     * Raised when the test ends. The stop condition depends on if the option
     * to loop was set to `true` or `false`. If `false`, then the test ends either
     * when the audio file is finished playing, or when a time has elapsed
     * greater than [[AudioOutputTest.Options.duration]].
     * @event
     * @param event [[AudioOutputTest.Events.End]]
     * @param listener A listener function that expects the following parameters
     * when the event is raised:
     * - A [[AudioOutputTest.Report]] that summarizes the run time of the test.
     * @returns This [[AudioOutputTest]] instance.
     */
    on(event: AudioOutputTest.Events.End, listener: (report: AudioOutputTest.Report) => any): this;
    /**
     * Raised when the test has run into an error, fatal or not.
     * @event
     * @param event [[AudioOutputTest.Events.Error]]
     * @param listener A listener function that expects the following parameters
     * when the event is raised:
     * - The [[DiagnosticError]].
     * @returns This [[AudioOutputTest]] instance.
     */
    on(event: AudioOutputTest.Events.Error, listener: (error: DiagnosticError) => any): this;
    /**
     * Raised every [[AudioOutputTest.Options.volumeEventIntervalMs]] after the test
     * starts successfully. Will have a `number` parameter representing the
     * current volume of the audio file.
     * @event
     * @param event [[AudioOutputTest.Events.Volume]]
     * @param listener A listener function that expects the following parameters
     * when the event is raised:
     * - A number representing the volume of the audio source.
     * @returns This [[AudioOutputTest]] instance.
     */
    on(event: AudioOutputTest.Events.Volume, listener: (value: number) => any): this;
}
/**
 * [[AudioOutputTest]] class that parses options and starts an audio output device
 * test.
 *
 * Please see [[testAudioOutputDevice]] for details and recommended practices.
 */
export declare class AudioOutputTest extends EventEmitter {
    /**
     * The name of the test.
     */
    static readonly testName: string;
    /**
     * Default options for the [[AudioOutputTest]]. Overwritten by any option passed
     * during the construction of the test.
     */
    private static defaultOptions;
    /**
     * Holds `AudioElement`s that are attached to the DOM to load and play audio.
     */
    private _audio;
    /**
     * An `AudioContext` that is used to process the audio source.
     */
    private _audioContext;
    /**
     * The default media devices when starting the test.
     */
    private _defaultDevices;
    /**
     * A timestamp of when the test ends.
     */
    private _endTime;
    /**
     * An array of errors encountered by the test during its run time.
     */
    private readonly _errors;
    /**
     * Options passed to and set in the constructor to be used during the run
     * time of the test.
     */
    private _options;
    /**
     * A timestamp of when the test starts. This is set in the constructor and not
     * when the test succesfully starts.
     */
    private _startTime;
    /**
     * Volume values generated by the test over its run time.
     */
    private readonly _values;
    /**
     * Timeout created by `setTimeout`, used to loop the volume logic.
     */
    private _volumeTimeout;
    /**
     * Sets up several things for the [[AudioOutputTest]] to run later in the
     * `_startTest` function.
     * @param options Optional settings to pass to the test.
     */
    constructor(options?: AudioOutputTest.Options);
    /**
     * Stops the test.
     */
    stop(): void;
    /**
     * Cleanup the test.
     */
    private _cleanup;
    /**
     * Error event handler. Adds the error to the internal list of errors that is
     * forwarded in the report.
     * @param error
     */
    private _onError;
    /**
     * Volume event handler, adds the value to the list `_values` and emits it
     * under the event `volume`.
     * @param volume
     */
    private _onVolume;
    /**
     * Warning event handler.
     * @param warning
     */
    private _onWarning;
    /**
     * Entry point of the test, called after setup in the constructor.
     * Emits the volume levels of the audio.
     *
     * @event [[AudioOutputTest.Events.Volume]]
     */
    private _startTest;
}
export declare namespace AudioOutputTest {
    /**
     * Events that the [[AudioOutputTest]] will emit as it runs.
     * Please see [[AudioOutputTest.on]] for how to listen to these
     * events.
     */
    enum Events {
        End = "end",
        Error = "error",
        Volume = "volume"
    }
    /**
     * Options passed to [[AudioOutputTest]] constructor.
     */
    interface Options {
        /**
         * An `AudioContext` to be used by the test.
         * @private
         */
        audioContextFactory?: typeof window.AudioContext;
        /**
         * A constuctor that is used to create an [[AudioElement]], useful for
         * mocks.
         * @private
         */
        audioElementFactory?: new (...args: any[]) => AudioElement;
        /**
         * Whether or not to log debug statements to the console.
         * @private
         */
        debug?: boolean;
        /**
         * The `deviceId` of the audio device to attempt to play audio out of.
         * This option is directly passed to [HTMLMediaElement.setSinkId](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/setSinkId).
         */
        deviceId?: string;
        /**
         * Whether or not to loop the audio.
         * See [[AudioOutputTest]] for details on the behavior of "timing out".
         * @default true
         */
        doLoop?: boolean;
        /**
         * Duration in milliseconds to run the test for. If this amount of time elapses, the test
         * is considered "timed out".
         * See [[AudioOutputTest]] for details on the behavior of "timing out".
         * @default Infinity
         */
        duration?: number;
        /**
         * Used to mock the call to `enumerateDevices`.
         * @private
         */
        enumerateDevices?: typeof navigator.mediaDevices.enumerateDevices;
        /**
         * The URI of the audio file to use for the test.
         */
        testURI?: string;
        /**
         * The interval between emissions of volume events in milliseconds.
         * @default 100
         */
        volumeEventIntervalMs?: number;
    }
    /**
     * Represents the report generated from an [[AudioOutputTest]].
     */
    interface Report {
        /**
         * The `deviceId` of the audio device used to play audio out of.
         */
        deviceId: string | undefined;
        /**
         * Any errors that occurred during the run-time of the [[AudioOutputTest]].
         */
        errors: DiagnosticError[];
        /**
         * Name of the test, set to [[AudioOutputTest.testName]].
         */
        testName: typeof AudioOutputTest.testName;
        /**
         * Time measurements of test run time.
         */
        testTiming: TimeMeasurement;
        /**
         * The URI of the audio file used during the test.
         */
        testURI?: string;
        /**
         * The volume values emitted by the test during its run-time.
         */
        values: number[];
    }
    /**
     * Option typing after initialization, so we can have type guarantees.
     * @private
     */
    type InternalOptions = SubsetRequired<Options, 'doLoop' | 'duration' | 'volumeEventIntervalMs' | 'testURI'>;
}
/**
 * [[AudioOutputTest]] tests audio output capabilities. It serves to help diagnose
 * potential audio device issues that would prevent a user from being able to
 * hear audio.
 *
 * ---
 *
 * The [[AudioOutputTest]] class is an `EventEmitter` (please see [[AudioOutputTest.on]] for
 * events and their details) and helps to diagnose issues by playing a sound clip
 * (by default the sound clip is the ringing tone from the `twilio-client.js`
 * SDK) and emitting volume events of the sound clip as it plays.
 * ```ts
 * import { AudioOutputTest, testAudioOutputDevice } from '@twilio/rtc-diagnostics';
 * const options: AudioOutputTest.Options = { ... };
 * // `options` may be left `undefined` to use default option values
 * const audioOutputTest: AudioOutputTest = testAudioOutputDevice(options);
 * ```
 * The application can use the volume events to show in its UI that audio is
 * playing and that the end-user should be hearing something.
 * ```ts
 * audioOutputTest.on(AudioOutputTest.Events.Volume, (volume: number) => {
 *   ui.updateVolume(volume); // Update your UI with the volume value here.
 * });
 * ```
 *
 * The application should ask the end-user to confirm that the sound being played
 * can be heard. The application should call [[AudioOutputTest.stop]] with `true` if
 * the end-user hears the sound, and `false` if not.
 * ```ts
 * // If the user was able to hear the audio, the UI should indicate they should
 * // click this button...
 * const passButton = ...;
 * passButton.on('click', () => {
 *   audioOutputTest.stop();
 *   // display a confirmation dialog to the user
 * });
 *
 * // ...conversely, if they were not able to hear the audio, they should click
 * // this one.
 * const failButton = ...;
 * failButton.on('click', () => {
 *   audioOutputTest.stop();
 *   // display a warning to the user
 * });
 * ```
 * Caling [[AudioOutputTest.stop]] will immediately end the test.
 *
 * ---
 *
 * The [[AudioOutputTest]] object will always emit a [[AudioOutputTest.Report]] with
 * the [[AudioOutputTest.Events.End]] event, regardless of the occurence of errors
 * during the runtime of the test.
 *
 * Fatal errors will immediately end the test and emit a report such that the
 * value of [[AudioOutputTest.Report.errors]] will contain the fatal error.
 *
 * Non-fatal errors will not end the test, but will be included in the value of
 * [[AudioOutputTest.Report.errors]] upon completion of the test.
 *
 * If the data at `testURI` is unable to be loaded, meaning the error event is
 * raised on the audio element, a fatal error has occurred.
 *
 * If `doLoop` is set to `false`, then the test will run for either the option
 * `duration`, or the full duration of the audio file, which ever is shorter.
 * If `doLoop` is set to `true`, it will only run as long as the `duration`
 * option.
 *
 * ---
 *
 * The function [[testAudioOutputDevice]] serves as factory function that accepts
 * [[AudioOutputTest.Options]] as its only parameter and will instantiate an
 * [[AudioOutputTest]] object with those options.
 * ```ts
 * import { AudioOutputTest, testAudioOutputDevice } from '@twilio/rtc-diagnostics';
 * const options: AudioOutputTest.Options = { ... };
 * const audioOutputTest: AudioOutputTest = testAudioOutputDevice(options);
 * ```
 * @param options Options to pass to the [[AudioOutputTest]] constructor.
 */
export declare function testAudioOutputDevice(options?: AudioOutputTest.Options): AudioOutputTest;
