ALC EXT Disconnect

 Name
   ALC_EXT_disconnect

 Contributors
   Ryan C. Gordon
   Stephen J. Baker
   Bob Aron
   Jason Daly
   Adam D. Moss
   Chris Robinson
   Eric Wing

 Contact
   Ryan C. Gordon (icculus 'at' icculus.org)

 Status
   Complete.

 Dependencies
   Written based on the OpenAL 1.0 specification
   ALC_ENUMERATION_EXT affects the definition of this extension.
   ALC_ENUMERATE_ALL_EXT affects the definition of this extension.
   ALC_EXT_capture affects the definition of this extension.

 Overview
   In OpenAL, there is no way to know if a device has been lost,
   nor is there a spec-approved means to deal with this properly.
   While most people are using either PCI audio cards or a chip
   welded to their motherboard, there are many devices that are
   more dynamic in nature, such as USB and Firewire based-units.
   Such units may lose external power seperate from the system,
   or may have their cables unplugged at runtime. The OS may
   reassign the hardware to a higher-priority process. If nothing
   else, a user may unplug the hardware without a proper shutdown
   (or properly shut them down at the OS level and not within the
   application).

   Other audio "devices" may vanish, too, such as the network
   connection that hosts a remote audio device like esound,
   nas, or arts.

   In these cases, the OpenAL spec says nothing, which we must
   assume means that all resulting behaviour is totally undefined,
   including everything from continued function without audio
   output to a crash within the AL.

   This extension, ALC_EXT_disconnect, strives to define AL
   behaviour in these cases and give the application a means to
   discover and deal with total device failure.

 Issues

   1. Should we make promises about buffer data post-disconnect?

      RESOLVED:  No.

      The AL currently supplies no means to recover buffer data,
      and all contexts sharing buffers must be on the same device.
      As such, all buffer data is lost in the event of a disconnect.
      The application will be required to reupload all their buffer
      data after opening a new device. If a future extension exposes
      a means to recover buffer data from the AL, it should amend
      this specification.

   2. What happens to queued buffers when a device is disconnected?
      Are they all considered "processed"?

      RESOLVED:  Yes and no.

      No, but all playing sources will be stopped on disconnect,
      which will cause their buffers to become processed. Newly
      started sources immediately stop, too. However, a source that
      has buffers queued but is not playing (PAUSED or INITIAL) will
      not have its queue altered unless the app attempts to start
      it with alSourcePlay(). This prevents apps from hanging while
      waiting for a sound to finish playback, and avoids the
      implementation needing further knowledge of buffer data once
      the device possibly containing it vanishes. On the other hand,
      time-sensitive programs may now run too quickly, but that seems
      to be a preferable situation.

   3. What should the AL do in the case of meta devices
      (generic device targets that doesn't cover specific
      hardware, such as "software mixer")?

      RESOLVED:  Platform-defined behaviour.

      This extension only cares about what to do with the AL when
      a device becomes disconnected, but we leave the definition of
      "disconnected" to the implementation. If it is possible to
      switch to another hardware device seamlessly and it would seem
      reasonable to the platform's users, then the implementation can
      feel free to do so without alerting the application in any way.
      This spec does not make any promises about disconnects of
      specific device names, or the default NULL device. These
      behaviours are only applicable once the implementation decides
      to set the ALC_CONNECTED attribute to zero.

   4. What promises should we make about the stability of the enumeration
      strings?

      RESOLVED:  Valid between enumeration requests.

      Device enumeration data should remain valid until the next 
      enumeration request. This prevents race conditions and allows a 
      well-defined point for device redetection. Most current
      implementations already do this, or at least do a detect on the
      first query.

 New procedures and functions
   None

 New tokens
   ALC_CONNECTED, 0x313.

 Additions to the 1.0 spec:

   Section 6.3.8, "Integer Query"

    Addition to table 6-4:

      ALC_CONNECTED
        Non-zero ALint if device is connected and functional.
        NULL is an invalid device.

   Section 6.4.3, "Device disconnect":

    If a device is unplugged, lost or otherwise damaged beyond
    functioning, the device is flagged as "disconnected" and
    the ALCdevice handle is considered a "zombie" device.

    When a device is disconnected, the implementation will, in
    most respects, keep processing as normal. For example, even
    though there is no longer any output when a USB audio
    device is removed, setting and querying state on the Listener
    should keep functioning as expected.

    All sources in the PLAYING state will immediately progress to
    STOPPED upon disconnect of their containing device. Any source
    started after the disconnect will immediately progress to 
    STOPPED. As in any stopped source, this also means that queued
    buffers all go to PROCESSED as well. Sources that are in the 
    PAUSED or INITIAL state do not change on disconnect, but will
    follow this behaviour if the application later tries to promote
    them to the PLAYING state.

    Zombie devices may not have new contexts created on them; 
    alcCreateContext() will fail, returning a NULL pointer, if
    the specified device has been disconnected.

    The application may determine if a device has been disconnected
    by using the ALC_CONNECTED token with alcGetIntegerv(). When a
    device has been disconnected, the application is permitted to
    close the zombie device's handle in the normal way, and may choose
    to open a new device.

    Applications that use ALC_CONNECTED are encouraged to query it with
    relative frequency. A game, for example, should call it once per
    rendering frame, per device. A device may become disconnected at
    any time without warning.

    Once a device is disconnected, it will never become reconnected.
    Even if the user plugs the device back in, the application must
    close the existing zombie device handle and reopen it with
    alc*OpenDevice().

    If device enumeration is available via ALC_ENUMERATION_EXT,
    ALC_ENUMERATE_ALL_EXT, or AL 1.1, the list of devices may change
    between calls as devices become disconnected and reconnected. 
    To prevent race conditions, the pointer to device list strings
    provided to the application will remain valid until the next call
    to alcGetString(). The implementation may either cache the result
    of the previous request or perform a complete device redetection 
    during the alcGetString() call. As such, enumeration may not be a
    "fast call" and should not be called in time-sensitive code.

    If capture devices are available via ALC_EXT_capture or AL 1.1,
    disconnection management can be used with both output and capture
    devices. A disconnected capture device will continue to function,
    but will not report a larger number in the ALC_CAPTURE_SAMPLES
    query. If the capture device had reported some number of samples
    were available but the samples were not transferred from the
    device to the AL at the time of disconnect, the AL should feed the
    application that amount of silence in the alcCaptureSamples() call.
    Future queries of ALC_CAPTURE_SAMPLES should report zero samples
    available.