Bunch of reworking to how we manage audio devices.
authorRyan C. Gordon <icculus@icculus.org>
Wed, 18 Mar 2015 02:01:17 -0400
changeset 9394bb28e5281770
parent 9393 ed79a66e57e5
child 9395 65e946d15533
Bunch of reworking to how we manage audio devices.

Device enumeration now happens at startup and then is managed exclusively
through hotplugging instead of full redetection. The device name list now has
a unique "handle" associated with each item and SDL will pass this to the
backend so they don't have to figure out how a human readable name maps to
real hardware for a second time.

Other cleanups, fixes, improvements, plus all the audio backends updated to
the new interface...largely untested at this point, though.
src/audio/SDL_audio.c
src/audio/SDL_audiodev.c
src/audio/SDL_audiodev_c.h
src/audio/SDL_sysaudio.h
src/audio/alsa/SDL_alsa_audio.c
src/audio/android/SDL_androidaudio.c
src/audio/arts/SDL_artsaudio.c
src/audio/bsd/SDL_bsdaudio.c
src/audio/coreaudio/SDL_coreaudio.c
src/audio/directsound/SDL_directsound.c
src/audio/disk/SDL_diskaudio.c
src/audio/dsp/SDL_dspaudio.c
src/audio/dummy/SDL_dummyaudio.c
src/audio/emscripten/SDL_emscriptenaudio.c
src/audio/esd/SDL_esdaudio.c
src/audio/fusionsound/SDL_fsaudio.c
src/audio/haiku/SDL_haikuaudio.cc
src/audio/nacl/SDL_naclaudio.c
src/audio/nas/SDL_nasaudio.c
src/audio/paudio/SDL_paudio.c
src/audio/psp/SDL_pspaudio.c
src/audio/pulseaudio/SDL_pulseaudio.c
src/audio/qsa/SDL_qsa_audio.c
src/audio/sndio/SDL_sndioaudio.c
src/audio/sun/SDL_sunaudio.c
src/audio/winmm/SDL_winmm.c
src/audio/xaudio2/SDL_xaudio2.c
     1.1 --- a/src/audio/SDL_audio.c	Mon Mar 16 02:11:39 2015 -0400
     1.2 +++ b/src/audio/SDL_audio.c	Wed Mar 18 02:01:17 2015 -0400
     1.3 @@ -161,8 +161,16 @@
     1.4  
     1.5  /* stubs for audio drivers that don't need a specific entry point... */
     1.6  static void
     1.7 -SDL_AudioDetectDevices_Default(int iscapture, SDL_AddAudioDevice addfn)
     1.8 -{                               /* no-op. */
     1.9 +SDL_AudioDetectDevices_Default(void)
    1.10 +{
    1.11 +    /* you have to write your own implementation if these assertions fail. */
    1.12 +    SDL_assert(current_audio.impl.OnlyHasDefaultOutputDevice);
    1.13 +    SDL_assert(current_audio.impl.OnlyHasDefaultInputDevice || !current_audio.impl.HasCaptureSupport);
    1.14 +
    1.15 +    SDL_AddAudioDevice(SDL_FALSE, DEFAULT_OUTPUT_DEVNAME, (void *) ((size_t) 0x1));
    1.16 +    if (current_audio.impl.HasCaptureSupport) {
    1.17 +        SDL_AddAudioDevice(SDL_TRUE, DEFAULT_INPUT_DEVNAME, (void *) ((size_t) 0x2));
    1.18 +    }
    1.19  }
    1.20  
    1.21  static void
    1.22 @@ -207,10 +215,16 @@
    1.23  {                               /* no-op. */
    1.24  }
    1.25  
    1.26 +static void
    1.27 +SDL_AudioFreeDeviceHandle_Default(void *handle)
    1.28 +{                               /* no-op. */
    1.29 +}
    1.30 +
    1.31 +
    1.32  static int
    1.33 -SDL_AudioOpenDevice_Default(_THIS, const char *devname, int iscapture)
    1.34 +SDL_AudioOpenDevice_Default(_THIS, void *handle, const char *devname, int iscapture)
    1.35  {
    1.36 -    return -1;
    1.37 +    return SDL_Unsupported();
    1.38  }
    1.39  
    1.40  static SDL_INLINE SDL_bool
    1.41 @@ -267,6 +281,7 @@
    1.42      FILL_STUB(CloseDevice);
    1.43      FILL_STUB(LockDevice);
    1.44      FILL_STUB(UnlockDevice);
    1.45 +    FILL_STUB(FreeDeviceHandle);
    1.46      FILL_STUB(Deinitialize);
    1.47  #undef FILL_STUB
    1.48  }
    1.49 @@ -335,94 +350,64 @@
    1.50  
    1.51  /* device hotplug support... */
    1.52  
    1.53 -/* this function expects its caller to hold current_audio.detection_lock */
    1.54  static int
    1.55 -add_audio_device(const char *_name, char ***_devices, int *_devCount)
    1.56 +add_audio_device(const char *name, void *handle, SDL_AudioDeviceItem **devices, int *devCount)
    1.57  {
    1.58 -    char *name = SDL_strdup(_name);
    1.59      int retval = -1;
    1.60 +    const size_t size = sizeof (SDL_AudioDeviceItem) + SDL_strlen(name) + 1;
    1.61 +    SDL_AudioDeviceItem *item = (SDL_AudioDeviceItem *) SDL_malloc(size);
    1.62 +    if (item == NULL) {
    1.63 +        return -1;
    1.64 +    }
    1.65  
    1.66 -    if (name != NULL) {
    1.67 -        char **devices = *_devices;
    1.68 -        int devCount = *_devCount;
    1.69 -        void *ptr = SDL_realloc(devices, (devCount+1) * sizeof(char*));
    1.70 -        if (ptr == NULL) {
    1.71 -            SDL_free(name);
    1.72 -        } else {
    1.73 -            retval = devCount;
    1.74 -            devices = (char **) ptr;
    1.75 -            devices[devCount++] = name;
    1.76 -            *_devices = devices;
    1.77 -            *_devCount = devCount;
    1.78 -        }
    1.79 -    }
    1.80 +    SDL_assert(handle != NULL);
    1.81 +
    1.82 +    item->handle = handle;
    1.83 +    SDL_strlcpy(item->name, name, size - sizeof (SDL_AudioDeviceItem));
    1.84 +
    1.85 +    SDL_LockMutex(current_audio.detectionLock);
    1.86 +    item->next = *devices;
    1.87 +    *devices = item;
    1.88 +    retval = (*devCount)++;
    1.89 +    SDL_UnlockMutex(current_audio.detectionLock);
    1.90  
    1.91      return retval;
    1.92  }
    1.93  
    1.94 -static int
    1.95 -add_capture_device(const char *name)
    1.96 +static SDL_INLINE int
    1.97 +add_capture_device(const char *name, void *handle)
    1.98  {
    1.99      /* !!! FIXME: add this later. SDL_assert(current_audio.impl.HasCaptureSupport);*/
   1.100 -    return add_audio_device(name, &current_audio.inputDevices, &current_audio.inputDeviceCount);
   1.101 +    return add_audio_device(name, handle, &current_audio.inputDevices, &current_audio.inputDeviceCount);
   1.102  }
   1.103  
   1.104 -static int
   1.105 -add_output_device(const char *name)
   1.106 +static SDL_INLINE int
   1.107 +add_output_device(const char *name, void *handle)
   1.108  {
   1.109 -    return add_audio_device(name, &current_audio.outputDevices, &current_audio.outputDeviceCount);
   1.110 +    return add_audio_device(name, handle, &current_audio.outputDevices, &current_audio.outputDeviceCount);
   1.111  }
   1.112  
   1.113  static void
   1.114 -free_device_list(char ***devices, int *devCount)
   1.115 +free_device_list(SDL_AudioDeviceItem **devices, int *devCount)
   1.116  {
   1.117 -    int i = *devCount;
   1.118 -    if ((i > 0) && (*devices != NULL)) {
   1.119 -        while (i--) {
   1.120 -            SDL_free((*devices)[i]);
   1.121 +    SDL_AudioDeviceItem *item, *next;
   1.122 +    for (item = *devices; item != NULL; item = next) {
   1.123 +        next = item->next;
   1.124 +        if (item->handle != NULL) {
   1.125 +            current_audio.impl.FreeDeviceHandle(item->handle);
   1.126          }
   1.127 +        SDL_free(item);
   1.128      }
   1.129 -
   1.130 -    SDL_free(*devices);
   1.131 -
   1.132      *devices = NULL;
   1.133      *devCount = 0;
   1.134  }
   1.135  
   1.136 -static void
   1.137 -perform_full_device_redetect(const int iscapture)
   1.138 -{
   1.139 -    SDL_LockMutex(current_audio.detection_lock);
   1.140 -
   1.141 -    if (iscapture) {
   1.142 -        if (!current_audio.impl.OnlyHasDefaultOutputDevice) {
   1.143 -            free_device_list(&current_audio.outputDevices, &current_audio.outputDeviceCount);
   1.144 -            current_audio.impl.DetectDevices(SDL_FALSE, add_output_device);
   1.145 -        }
   1.146 -    } else {
   1.147 -        if ((current_audio.impl.HasCaptureSupport) && (!current_audio.impl.OnlyHasDefaultInputDevice)) {
   1.148 -            free_device_list(&current_audio.inputDevices, &current_audio.inputDeviceCount);
   1.149 -            current_audio.impl.DetectDevices(SDL_TRUE, add_capture_device);
   1.150 -        }
   1.151 -    }
   1.152 -
   1.153 -    SDL_UnlockMutex(current_audio.detection_lock);
   1.154 -}
   1.155  
   1.156  /* The audio backends call this when a new device is plugged in. */
   1.157  void
   1.158 -SDL_AudioDeviceConnected(const int iscapture, const char *name)
   1.159 +SDL_AddAudioDevice(const int iscapture, const char *name, void *handle)
   1.160  {
   1.161 -    int device_index = -1;
   1.162 -
   1.163 -    SDL_LockMutex(current_audio.detection_lock);
   1.164 -    if (iscapture) {
   1.165 -        device_index = add_capture_device(name);
   1.166 -    } else {
   1.167 -        device_index = add_output_device(name);
   1.168 -    }
   1.169 -    SDL_UnlockMutex(current_audio.detection_lock);
   1.170 -
   1.171 +    const int device_index = iscapture ? add_capture_device(name, handle) : add_output_device(name, handle);
   1.172      if (device_index != -1) {
   1.173          /* Post the event, if desired */
   1.174          if (SDL_GetEventState(SDL_AUDIODEVICEADDED) == SDL_ENABLE) {
   1.175 @@ -435,39 +420,51 @@
   1.176      }
   1.177  }
   1.178  
   1.179 -/* The audio backends call this when a device is unplugged. */
   1.180 -void
   1.181 -SDL_AudioDeviceDisconnected(const int iscapture, SDL_AudioDevice *device)
   1.182 +/* The audio backends call this when a currently-opened device is lost. */
   1.183 +void SDL_OpenedAudioDeviceDisconnected(SDL_AudioDevice *device)
   1.184  {
   1.185 -    /* device==NULL means an unopened device was lost; do the redetect only. */
   1.186 -    if (device != NULL) {
   1.187 -        SDL_assert(get_audio_device(device->id) == device);
   1.188 -        SDL_assert(device->enabled);  /* called more than once?! */
   1.189 +    SDL_assert(get_audio_device(device->id) == device);
   1.190 +    SDL_assert(device->enabled);  /* called more than once?! */
   1.191  
   1.192 -        /* Ends the audio callback and mark the device as STOPPED, but the
   1.193 -           app still needs to close the device to free resources. */
   1.194 -        current_audio.impl.LockDevice(device);
   1.195 -        device->enabled = 0;
   1.196 -        current_audio.impl.UnlockDevice(device);
   1.197 +    /* Ends the audio callback and mark the device as STOPPED, but the
   1.198 +       app still needs to close the device to free resources. */
   1.199 +    current_audio.impl.LockDevice(device);
   1.200 +    device->enabled = 0;
   1.201 +    current_audio.impl.UnlockDevice(device);
   1.202  
   1.203 -        /* Post the event, if desired */
   1.204 -        if (SDL_GetEventState(SDL_AUDIODEVICEREMOVED) == SDL_ENABLE) {
   1.205 -            SDL_Event event;
   1.206 -            event.adevice.type = SDL_AUDIODEVICEREMOVED;
   1.207 -            event.adevice.which = device->id;
   1.208 -            event.adevice.iscapture = device->iscapture ? 1 : 0;
   1.209 -            SDL_PushEvent(&event);
   1.210 +    /* Post the event, if desired */
   1.211 +    if (SDL_GetEventState(SDL_AUDIODEVICEREMOVED) == SDL_ENABLE) {
   1.212 +        SDL_Event event;
   1.213 +        event.adevice.type = SDL_AUDIODEVICEREMOVED;
   1.214 +        event.adevice.which = device->id;
   1.215 +        event.adevice.iscapture = device->iscapture ? 1 : 0;
   1.216 +        SDL_PushEvent(&event);
   1.217 +    }
   1.218 +}
   1.219 +
   1.220 +static void
   1.221 +mark_device_removed(void *handle, SDL_AudioDeviceItem *devices, SDL_bool *removedFlag)
   1.222 +{
   1.223 +    SDL_AudioDeviceItem *item;
   1.224 +    SDL_assert(handle != NULL);
   1.225 +    for (item = devices; item != NULL; item = item->next) {
   1.226 +        if (item->handle == handle) {
   1.227 +            item->handle = NULL;
   1.228 +            *removedFlag = SDL_TRUE;
   1.229 +            return;
   1.230          }
   1.231      }
   1.232 +}
   1.233  
   1.234 -    /* we don't really know which name (if any) was associated with this
   1.235 -       device in the device list, so drop the entire list and rebuild it.
   1.236 -       (we should probably change the API in 2.1 to make this more clear?) */
   1.237 -    if (iscapture) {
   1.238 -        current_audio.need_capture_device_redetect = SDL_TRUE;
   1.239 -    } else {
   1.240 -        current_audio.need_output_device_redetect = SDL_TRUE;
   1.241 -    }
   1.242 +/* The audio backends call this when a device is removed from the system. */
   1.243 +void
   1.244 +SDL_RemoveAudioDevice(void *handle)
   1.245 +{
   1.246 +    SDL_LockMutex(current_audio.detectionLock);
   1.247 +    mark_device_removed(handle, current_audio.inputDevices, &current_audio.captureDevicesRemoved);
   1.248 +    mark_device_removed(handle, current_audio.outputDevices, &current_audio.outputDevicesRemoved);
   1.249 +    SDL_UnlockMutex(current_audio.detectionLock);
   1.250 +    current_audio.impl.FreeDeviceHandle(handle);
   1.251  }
   1.252  
   1.253  
   1.254 @@ -966,33 +963,12 @@
   1.255          return -1;            /* No driver was available, so fail. */
   1.256      }
   1.257  
   1.258 -    current_audio.detection_lock = SDL_CreateMutex();
   1.259 +    current_audio.detectionLock = SDL_CreateMutex();
   1.260  
   1.261      finalize_audio_entry_points();
   1.262  
   1.263      /* Make sure we have a list of devices available at startup. */
   1.264 -    perform_full_device_redetect(SDL_TRUE);
   1.265 -    perform_full_device_redetect(SDL_FALSE);
   1.266 -
   1.267 -    /* Post an add event for each initial device, if desired */
   1.268 -    if (SDL_GetEventState(SDL_AUDIODEVICEADDED) == SDL_ENABLE) {
   1.269 -        SDL_Event event;
   1.270 -
   1.271 -        SDL_zero(event);
   1.272 -        event.adevice.type = SDL_AUDIODEVICEADDED;
   1.273 -
   1.274 -        event.adevice.iscapture = 0;
   1.275 -        for (i = 0; i < current_audio.outputDeviceCount; i++) {
   1.276 -            event.adevice.which = i;
   1.277 -            SDL_PushEvent(&event);
   1.278 -        }
   1.279 -
   1.280 -        event.adevice.iscapture = 1;
   1.281 -        for (i = 0; i < current_audio.inputDeviceCount; i++) {
   1.282 -            event.adevice.which = i;
   1.283 -            SDL_PushEvent(&event);
   1.284 -        }
   1.285 -    }
   1.286 +    current_audio.impl.DetectDevices();
   1.287  
   1.288      return 0;
   1.289  }
   1.290 @@ -1006,6 +982,35 @@
   1.291      return current_audio.name;
   1.292  }
   1.293  
   1.294 +/* Clean out devices that we've removed but had to keep around for stability. */
   1.295 +static void
   1.296 +clean_out_device_list(SDL_AudioDeviceItem **devices, int *devCount, SDL_bool *removedFlag)
   1.297 +{
   1.298 +    SDL_AudioDeviceItem *item = *devices;
   1.299 +    SDL_AudioDeviceItem *prev = NULL;
   1.300 +    int total = 0;
   1.301 +
   1.302 +    while (item) {
   1.303 +        SDL_AudioDeviceItem *next = item->next;
   1.304 +        if (item->handle != NULL) {
   1.305 +            total++;
   1.306 +            prev = item;
   1.307 +        } else {
   1.308 +            if (prev) {
   1.309 +                prev->next = next;
   1.310 +            } else {
   1.311 +                *devices = next;
   1.312 +            }
   1.313 +            SDL_free(item);
   1.314 +        }
   1.315 +        item = next;
   1.316 +    }
   1.317 +
   1.318 +    *devCount = total;
   1.319 +    *removedFlag = SDL_FALSE;
   1.320 +}
   1.321 +
   1.322 +
   1.323  int
   1.324  SDL_GetNumAudioDevices(int iscapture)
   1.325  {
   1.326 @@ -1015,31 +1020,18 @@
   1.327          return -1;
   1.328      }
   1.329  
   1.330 -    if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) {
   1.331 -        return 0;
   1.332 +    SDL_LockMutex(current_audio.detectionLock);
   1.333 +    if (iscapture && current_audio.captureDevicesRemoved) {
   1.334 +        clean_out_device_list(&current_audio.inputDevices, &current_audio.inputDeviceCount, &current_audio.captureDevicesRemoved);
   1.335      }
   1.336  
   1.337 -    if ((iscapture) && (current_audio.impl.OnlyHasDefaultInputDevice)) {
   1.338 -        return 1;
   1.339 +    if (!iscapture && current_audio.outputDevicesRemoved) {
   1.340 +        clean_out_device_list(&current_audio.outputDevices, &current_audio.outputDeviceCount, &current_audio.outputDevicesRemoved);
   1.341 +        current_audio.outputDevicesRemoved = SDL_FALSE;
   1.342      }
   1.343  
   1.344 -    if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) {
   1.345 -        return 1;
   1.346 -    }
   1.347 -
   1.348 -    if (current_audio.need_capture_device_redetect) {
   1.349 -        current_audio.need_capture_device_redetect = SDL_FALSE;
   1.350 -        perform_full_device_redetect(SDL_TRUE);
   1.351 -    }
   1.352 -
   1.353 -    if (current_audio.need_output_device_redetect) {
   1.354 -        current_audio.need_output_device_redetect = SDL_FALSE;
   1.355 -        perform_full_device_redetect(SDL_FALSE);
   1.356 -    }
   1.357 -
   1.358 -    SDL_LockMutex(current_audio.detection_lock);
   1.359      retval = iscapture ? current_audio.inputDeviceCount : current_audio.outputDeviceCount;
   1.360 -    SDL_UnlockMutex(current_audio.detection_lock);
   1.361 +    SDL_UnlockMutex(current_audio.detectionLock);
   1.362  
   1.363      return retval;
   1.364  }
   1.365 @@ -1060,41 +1052,28 @@
   1.366          return NULL;
   1.367      }
   1.368  
   1.369 -    if (index < 0) {
   1.370 -        goto no_such_device;
   1.371 +    if (index >= 0) {
   1.372 +        SDL_AudioDeviceItem *item;
   1.373 +        int i;
   1.374 +
   1.375 +        SDL_LockMutex(current_audio.detectionLock);
   1.376 +        item = iscapture ? current_audio.inputDevices : current_audio.outputDevices;
   1.377 +        i = iscapture ? current_audio.inputDeviceCount : current_audio.outputDeviceCount;
   1.378 +        if (index < i) {
   1.379 +            for (i--; i > index; i--, item = item->next) {
   1.380 +                SDL_assert(item != NULL);
   1.381 +            }
   1.382 +            SDL_assert(item != NULL);
   1.383 +            retval = item->name;
   1.384 +        }
   1.385 +        SDL_UnlockMutex(current_audio.detectionLock);
   1.386      }
   1.387  
   1.388 -    if ((iscapture) && (current_audio.impl.OnlyHasDefaultInputDevice)) {
   1.389 -        if (index > 0) {
   1.390 -            goto no_such_device;
   1.391 -        }
   1.392 -        return DEFAULT_INPUT_DEVNAME;
   1.393 +    if (retval == NULL) {
   1.394 +        SDL_SetError("No such device");
   1.395      }
   1.396  
   1.397 -    if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) {
   1.398 -        if (index > 0) {
   1.399 -            goto no_such_device;
   1.400 -        }
   1.401 -        return DEFAULT_OUTPUT_DEVNAME;
   1.402 -    }
   1.403 -
   1.404 -    SDL_LockMutex(current_audio.detection_lock);
   1.405 -    if (iscapture && (index < current_audio.inputDeviceCount)) {
   1.406 -        retval = current_audio.inputDevices[index];
   1.407 -    } else if (!iscapture && (index < current_audio.outputDeviceCount)) {
   1.408 -        retval = current_audio.outputDevices[index];
   1.409 -    }
   1.410 -    SDL_UnlockMutex(current_audio.detection_lock);
   1.411 -
   1.412 -    /* !!! FIXME: a device could be removed after being returned here, freeing retval's pointer. */
   1.413 -
   1.414 -    if (retval != NULL) {
   1.415 -        return retval;
   1.416 -    }
   1.417 -
   1.418 -no_such_device:
   1.419 -    SDL_SetError("No such device");
   1.420 -    return NULL;
   1.421 +    return retval;
   1.422  }
   1.423  
   1.424  
   1.425 @@ -1195,6 +1174,7 @@
   1.426      SDL_AudioSpec _obtained;
   1.427      SDL_AudioDevice *device;
   1.428      SDL_bool build_cvt;
   1.429 +    void *handle = NULL;
   1.430      int i = 0;
   1.431  
   1.432      if (!SDL_WasInit(SDL_INIT_AUDIO)) {
   1.433 @@ -1254,9 +1234,7 @@
   1.434                  return 0;
   1.435              }
   1.436          }
   1.437 -    }
   1.438 -
   1.439 -    if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) {
   1.440 +    } else if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) {
   1.441          if ((devname) && (SDL_strcmp(devname, DEFAULT_OUTPUT_DEVNAME) != 0)) {
   1.442              SDL_SetError("No such device");
   1.443              return 0;
   1.444 @@ -1269,6 +1247,30 @@
   1.445                  return 0;
   1.446              }
   1.447          }
   1.448 +    } else if (devname != NULL) {
   1.449 +        /* if the app specifies an exact string, we can pass the backend
   1.450 +           an actual device handle thingey, which saves them the effort of
   1.451 +           figuring out what device this was (such as, reenumerating
   1.452 +           everything again to find the matching human-readable name).
   1.453 +           It might still need to open a device based on the string for,
   1.454 +           say, a network audio server, but this optimizes some cases. */
   1.455 +        SDL_AudioDeviceItem *item;
   1.456 +        SDL_LockMutex(current_audio.detectionLock);
   1.457 +        for (item = iscapture ? current_audio.inputDevices : current_audio.outputDevices; item; item = item->next) {
   1.458 +            if ((item->handle != NULL) && (SDL_strcmp(item->name, devname) == 0)) {
   1.459 +                handle = item->handle;
   1.460 +                break;
   1.461 +            }
   1.462 +        }
   1.463 +        SDL_UnlockMutex(current_audio.detectionLock);
   1.464 +    }
   1.465 +
   1.466 +    if (!current_audio.impl.AllowsArbitraryDeviceNames) {
   1.467 +        /* has to be in our device list, or the default device. */
   1.468 +        if ((handle == NULL) && (devname != NULL)) {
   1.469 +            SDL_SetError("No such device.");
   1.470 +            return 0;
   1.471 +        }
   1.472      }
   1.473  
   1.474      device = (SDL_AudioDevice *) SDL_AllocAudioMem(sizeof(SDL_AudioDevice));
   1.475 @@ -1293,7 +1295,7 @@
   1.476          }
   1.477      }
   1.478  
   1.479 -    if (current_audio.impl.OpenDevice(device, devname, iscapture) < 0) {
   1.480 +    if (current_audio.impl.OpenDevice(device, handle, devname, iscapture) < 0) {
   1.481          close_audio_device(device);
   1.482          return 0;
   1.483      }
   1.484 @@ -1555,15 +1557,13 @@
   1.485          }
   1.486      }
   1.487  
   1.488 +    free_device_list(&current_audio.outputDevices, &current_audio.outputDeviceCount);
   1.489 +    free_device_list(&current_audio.inputDevices, &current_audio.inputDeviceCount);
   1.490 +
   1.491      /* Free the driver data */
   1.492      current_audio.impl.Deinitialize();
   1.493  
   1.494 -    free_device_list(&current_audio.outputDevices,
   1.495 -                     &current_audio.outputDeviceCount);
   1.496 -    free_device_list(&current_audio.inputDevices,
   1.497 -                     &current_audio.inputDeviceCount);
   1.498 -
   1.499 -    SDL_DestroyMutex(current_audio.detection_lock);
   1.500 +    SDL_DestroyMutex(current_audio.detectionLock);
   1.501  
   1.502      SDL_zero(current_audio);
   1.503      SDL_zero(open_devices);
     2.1 --- a/src/audio/SDL_audiodev.c	Mon Mar 16 02:11:39 2015 -0400
     2.2 +++ b/src/audio/SDL_audiodev.c	Wed Mar 18 02:01:17 2015 -0400
     2.3 @@ -46,18 +46,21 @@
     2.4  #define _PATH_DEV_AUDIO "/dev/audio"
     2.5  #endif
     2.6  
     2.7 -static SDL_INLINE void
     2.8 -test_device(const char *fname, int flags, int (*test) (int fd),
     2.9 -            SDL_AddAudioDevice addfn)
    2.10 +static void
    2.11 +test_device(const int iscapture, const char *fname, int flags, int (*test) (int fd))
    2.12  {
    2.13      struct stat sb;
    2.14      if ((stat(fname, &sb) == 0) && (S_ISCHR(sb.st_mode))) {
    2.15          const int audio_fd = open(fname, flags, 0);
    2.16          if (audio_fd >= 0) {
    2.17 -            if (test(audio_fd)) {
    2.18 -                addfn(fname);
    2.19 +            const int okay = test(audio_fd);
    2.20 +            close(audio_fd);
    2.21 +            if (okay) {
    2.22 +                static size_t dummyhandle = 0;
    2.23 +                dummyhandle++;
    2.24 +                SDL_assert(dummyhandle != 0);
    2.25 +                SDL_AddAudioDevice(iscapture, fname, (void *) dummyhandle);
    2.26              }
    2.27 -            close(audio_fd);
    2.28          }
    2.29      }
    2.30  }
    2.31 @@ -68,11 +71,10 @@
    2.32      return 1;
    2.33  }
    2.34  
    2.35 -void
    2.36 -SDL_EnumUnixAudioDevices(int iscapture, int classic, int (*test)(int fd),
    2.37 -                         SDL_AddAudioDevice addfn)
    2.38 +static void
    2.39 +SDL_EnumUnixAudioDevices_Internal(const int iscapture, const int classic, int (*test)(int))
    2.40  {
    2.41 -    const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT);
    2.42 +    const int flags = iscapture ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT;
    2.43      const char *audiodev;
    2.44      char audiopath[1024];
    2.45  
    2.46 @@ -97,17 +99,25 @@
    2.47              }
    2.48          }
    2.49      }
    2.50 -    test_device(audiodev, flags, test, addfn);
    2.51 +    test_device(iscapture, audiodev, flags, test);
    2.52  
    2.53      if (SDL_strlen(audiodev) < (sizeof(audiopath) - 3)) {
    2.54          int instance = 0;
    2.55          while (instance++ <= 64) {
    2.56              SDL_snprintf(audiopath, SDL_arraysize(audiopath),
    2.57                           "%s%d", audiodev, instance);
    2.58 -            test_device(audiopath, flags, test, addfn);
    2.59 +            test_device(iscapture, audiopath, flags, test);
    2.60          }
    2.61      }
    2.62  }
    2.63  
    2.64 +void
    2.65 +SDL_EnumUnixAudioDevices(const int classic, int (*test)(int))
    2.66 +{
    2.67 +    SDL_EnumUnixAudioDevices_Internal(SDL_TRUE, classic, test);
    2.68 +    SDL_EnumUnixAudioDevices_Internal(SDL_FALSE, classic, test);
    2.69 +}
    2.70 +
    2.71  #endif /* Audio driver selection */
    2.72 +
    2.73  /* vi: set ts=4 sw=4 expandtab: */
     3.1 --- a/src/audio/SDL_audiodev_c.h	Mon Mar 16 02:11:39 2015 -0400
     3.2 +++ b/src/audio/SDL_audiodev_c.h	Wed Mar 18 02:01:17 2015 -0400
     3.3 @@ -33,7 +33,6 @@
     3.4  #define OPEN_FLAGS_INPUT (O_RDONLY|O_NONBLOCK)
     3.5  #endif
     3.6  
     3.7 -void SDL_EnumUnixAudioDevices(int iscapture, int classic,
     3.8 -                              int (*test) (int fd), SDL_AddAudioDevice addfn);
     3.9 +extern void SDL_EnumUnixAudioDevices(const int classic, int (*test)(int));
    3.10  
    3.11  /* vi: set ts=4 sw=4 expandtab: */
     4.1 --- a/src/audio/SDL_sysaudio.h	Mon Mar 16 02:11:39 2015 -0400
     4.2 +++ b/src/audio/SDL_sysaudio.h	Wed Mar 18 02:01:17 2015 -0400
     4.3 @@ -30,16 +30,20 @@
     4.4  typedef struct SDL_AudioDevice SDL_AudioDevice;
     4.5  #define _THIS   SDL_AudioDevice *_this
     4.6  
     4.7 -/* Used by audio targets during DetectDevices() */
     4.8 -typedef int (*SDL_AddAudioDevice)(const char *name);
     4.9 +/* Audio targets should call this as devices are added to the system (such as
    4.10 +   a USB headset being plugged in), and should also be called for
    4.11 +   for every device found during DetectDevices(). */
    4.12 +extern void SDL_AddAudioDevice(const int iscapture, const char *name, void *handle);
    4.13  
    4.14 -/* Audio targets should call this as devices are hotplugged. Don't call
    4.15 -   during DetectDevices(), this is for hotplugging a device later. */
    4.16 -extern void SDL_AudioDeviceConnected(const int iscapture, const char *name);
    4.17 +/* Audio targets should call this as devices are removed, so SDL can update
    4.18 +   its list of available devices. */
    4.19 +extern void SDL_RemoveAudioDevice(void *handle);
    4.20  
    4.21 -/* Audio targets should call this as devices are unplugged.
    4.22 -  (device) can be NULL if an unopened device is lost. */
    4.23 -extern void SDL_AudioDeviceDisconnected(const int iscapture, SDL_AudioDevice *device);
    4.24 +/* Audio targets should call this if an opened audio device is lost while
    4.25 +   being used. This can happen due to i/o errors, or a device being unplugged,
    4.26 +   etc. If the device is totally gone, please also call SDL_RemoveAudioDevice()
    4.27 +   as appropriate so SDL's list of devices is accurate. */
    4.28 +extern void SDL_OpenedAudioDeviceDisconnected(SDL_AudioDevice *device);
    4.29  
    4.30  
    4.31  /* This is the size of a packet when using SDL_QueueAudio(). We allocate
    4.32 @@ -64,8 +68,8 @@
    4.33  
    4.34  typedef struct SDL_AudioDriverImpl
    4.35  {
    4.36 -    void (*DetectDevices) (int iscapture, SDL_AddAudioDevice addfn);
    4.37 -    int (*OpenDevice) (_THIS, const char *devname, int iscapture);
    4.38 +    void (*DetectDevices) (void);
    4.39 +    int (*OpenDevice) (_THIS, void *handle, const char *devname, int iscapture);
    4.40      void (*ThreadInit) (_THIS); /* Called by audio thread at start */
    4.41      void (*WaitDevice) (_THIS);
    4.42      void (*PlayDevice) (_THIS);
    4.43 @@ -75,6 +79,7 @@
    4.44      void (*CloseDevice) (_THIS);
    4.45      void (*LockDevice) (_THIS);
    4.46      void (*UnlockDevice) (_THIS);
    4.47 +    void (*FreeDeviceHandle) (void *handle);  /**< SDL is done with handle from SDL_AddAudioDevice() */
    4.48      void (*Deinitialize) (void);
    4.49  
    4.50      /* !!! FIXME: add pause(), so we can optimize instead of mixing silence. */
    4.51 @@ -86,9 +91,18 @@
    4.52      int HasCaptureSupport;
    4.53      int OnlyHasDefaultOutputDevice;
    4.54      int OnlyHasDefaultInputDevice;
    4.55 +    int AllowsArbitraryDeviceNames;
    4.56  } SDL_AudioDriverImpl;
    4.57  
    4.58  
    4.59 +typedef struct SDL_AudioDeviceItem
    4.60 +{
    4.61 +    void *handle;
    4.62 +    struct SDL_AudioDeviceItem *next;
    4.63 +    char name[];
    4.64 +} SDL_AudioDeviceItem;
    4.65 +
    4.66 +
    4.67  typedef struct SDL_AudioDriver
    4.68  {
    4.69      /* * * */
    4.70 @@ -102,16 +116,13 @@
    4.71      SDL_AudioDriverImpl impl;
    4.72  
    4.73      /* A mutex for device detection */
    4.74 -    SDL_mutex *detection_lock;
    4.75 -
    4.76 -    SDL_bool need_capture_device_redetect;
    4.77 -    SDL_bool need_output_device_redetect;
    4.78 -
    4.79 -    char **outputDevices;
    4.80 +    SDL_mutex *detectionLock;
    4.81 +    SDL_bool captureDevicesRemoved;
    4.82 +    SDL_bool outputDevicesRemoved;
    4.83      int outputDeviceCount;
    4.84 -
    4.85 -    char **inputDevices;
    4.86      int inputDeviceCount;
    4.87 +    SDL_AudioDeviceItem *outputDevices;
    4.88 +    SDL_AudioDeviceItem *inputDevices;
    4.89  } SDL_AudioDriver;
    4.90  
    4.91  
     5.1 --- a/src/audio/alsa/SDL_alsa_audio.c	Mon Mar 16 02:11:39 2015 -0400
     5.2 +++ b/src/audio/alsa/SDL_alsa_audio.c	Wed Mar 18 02:01:17 2015 -0400
     5.3 @@ -320,7 +320,7 @@
     5.4                  /* Hmm, not much we can do - abort */
     5.5                  fprintf(stderr, "ALSA write failed (unrecoverable): %s\n",
     5.6                          ALSA_snd_strerror(status));
     5.7 -                SDL_AudioDeviceDisconnected(SDL_FALSE, this);
     5.8 +                SDL_OpenedAudioDeviceDisconnected(this);
     5.9                  return;
    5.10              }
    5.11              continue;
    5.12 @@ -465,7 +465,7 @@
    5.13  }
    5.14  
    5.15  static int
    5.16 -ALSA_OpenDevice(_THIS, const char *devname, int iscapture)
    5.17 +ALSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
    5.18  {
    5.19      int status = 0;
    5.20      snd_pcm_t *pcm_handle = NULL;
     6.1 --- a/src/audio/android/SDL_androidaudio.c	Mon Mar 16 02:11:39 2015 -0400
     6.2 +++ b/src/audio/android/SDL_androidaudio.c	Wed Mar 18 02:01:17 2015 -0400
     6.3 @@ -35,7 +35,7 @@
     6.4  static SDL_AudioDevice* audioDevice = NULL;
     6.5  
     6.6  static int
     6.7 -AndroidAUD_OpenDevice(_THIS, const char *devname, int iscapture)
     6.8 +AndroidAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     6.9  {
    6.10      SDL_AudioFormat test_format;
    6.11  
     7.1 --- a/src/audio/arts/SDL_artsaudio.c	Mon Mar 16 02:11:39 2015 -0400
     7.2 +++ b/src/audio/arts/SDL_artsaudio.c	Wed Mar 18 02:01:17 2015 -0400
     7.3 @@ -151,7 +151,7 @@
     7.4          /* Check every 10 loops */
     7.5          if (this->hidden->parent && (((++cnt) % 10) == 0)) {
     7.6              if (kill(this->hidden->parent, 0) < 0 && errno == ESRCH) {
     7.7 -                SDL_AudioDeviceDisconnected(SDL_FALSE, this);
     7.8 +                SDL_OpenedAudioDeviceDisconnected(this);
     7.9              }
    7.10          }
    7.11      }
    7.12 @@ -179,7 +179,7 @@
    7.13  
    7.14      /* If we couldn't write, assume fatal error for now */
    7.15      if (written < 0) {
    7.16 -        SDL_AudioDeviceDisconnected(SDL_FALSE, this);
    7.17 +        SDL_OpenedAudioDeviceDisconnected(this);
    7.18      }
    7.19  #ifdef DEBUG_AUDIO
    7.20      fprintf(stderr, "Wrote %d bytes of audio data\n", written);
    7.21 @@ -229,7 +229,7 @@
    7.22  }
    7.23  
    7.24  static int
    7.25 -ARTS_OpenDevice(_THIS, const char *devname, int iscapture)
    7.26 +ARTS_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
    7.27  {
    7.28      int rc = 0;
    7.29      int bits = 0, frag_spec = 0;
     8.1 --- a/src/audio/bsd/SDL_bsdaudio.c	Mon Mar 16 02:11:39 2015 -0400
     8.2 +++ b/src/audio/bsd/SDL_bsdaudio.c	Wed Mar 18 02:01:17 2015 -0400
     8.3 @@ -51,9 +51,9 @@
     8.4  
     8.5  
     8.6  static void
     8.7 -BSDAUDIO_DetectDevices(int iscapture, SDL_AddAudioDevice addfn)
     8.8 +BSDAUDIO_DetectDevices(void)
     8.9  {
    8.10 -    SDL_EnumUnixAudioDevices(iscapture, 0, NULL, addfn);
    8.11 +    SDL_EnumUnixAudioDevices(0, NULL);
    8.12  }
    8.13  
    8.14  
    8.15 @@ -150,7 +150,7 @@
    8.16                 the user know what happened.
    8.17               */
    8.18              fprintf(stderr, "SDL: %s\n", message);
    8.19 -            SDL_AudioDeviceDisconnected(SDL_FALSE, this);
    8.20 +            SDL_OpenedAudioDeviceDisconnected(this);
    8.21              /* Don't try to close - may hang */
    8.22              this->hidden->audio_fd = -1;
    8.23  #ifdef DEBUG_AUDIO
    8.24 @@ -195,7 +195,7 @@
    8.25  
    8.26      /* If we couldn't write, assume fatal error for now */
    8.27      if (written < 0) {
    8.28 -        SDL_AudioDeviceDisconnected(SDL_FALSE, this);
    8.29 +        SDL_OpenedAudioDeviceDisconnected(this);
    8.30      }
    8.31  #ifdef DEBUG_AUDIO
    8.32      fprintf(stderr, "Wrote %d bytes of audio data\n", written);
    8.33 @@ -224,7 +224,7 @@
    8.34  }
    8.35  
    8.36  static int
    8.37 -BSDAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
    8.38 +BSDAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
    8.39  {
    8.40      const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT);
    8.41      SDL_AudioFormat format = 0;
    8.42 @@ -348,6 +348,8 @@
    8.43      impl->GetDeviceBuf = BSDAUDIO_GetDeviceBuf;
    8.44      impl->CloseDevice = BSDAUDIO_CloseDevice;
    8.45  
    8.46 +    impl->AllowsArbitraryDeviceNames = 1;
    8.47 +
    8.48      return 1;   /* this audio target is available. */
    8.49  }
    8.50  
     9.1 --- a/src/audio/coreaudio/SDL_coreaudio.c	Mon Mar 16 02:11:39 2015 -0400
     9.2 +++ b/src/audio/coreaudio/SDL_coreaudio.c	Wed Mar 18 02:01:17 2015 -0400
     9.3 @@ -80,28 +80,8 @@
     9.4  static void
     9.5  addToDevList(const char *name, const int iscapture, AudioDeviceID devId, void *data)
     9.6  {
     9.7 -    SDL_AddAudioDevice addfn = (SDL_AddAudioDevice) data;
     9.8      if (add_to_internal_dev_list(iscapture, devId)) {
     9.9 -        addfn(name);
    9.10 -    }
    9.11 -}
    9.12 -
    9.13 -typedef struct
    9.14 -{
    9.15 -    const char *findname;
    9.16 -    AudioDeviceID devId;
    9.17 -    int found;
    9.18 -} FindDevIdData;
    9.19 -
    9.20 -static void
    9.21 -findDevId(const char *name, const int iscapture, AudioDeviceID devId, void *_data)
    9.22 -{
    9.23 -    FindDevIdData *data = (FindDevIdData *) _data;
    9.24 -    if (!data->found) {
    9.25 -        if (SDL_strcmp(name, data->findname) == 0) {
    9.26 -            data->found = 1;
    9.27 -            data->devId = devId;
    9.28 -        }
    9.29 +        SDL_AddAudioDevice(iscapture, name, (void *) ((size_t) devId));
    9.30      }
    9.31  }
    9.32  
    9.33 @@ -226,10 +206,10 @@
    9.34  }
    9.35  
    9.36  static void
    9.37 -COREAUDIO_DetectDevices(int iscapture, SDL_AddAudioDevice addfn)
    9.38 +COREAUDIO_DetectDevices(void)
    9.39  {
    9.40 -    free_audio_device_list(iscapture ? &capture_devs : &output_devs);
    9.41 -    build_device_list(iscapture, addToDevList, addfn);
    9.42 +    build_device_list(SDL_TRUE, addToDevList, NULL);
    9.43 +    build_device_list(SDL_FALSE, addToDevList, NULL);
    9.44  }
    9.45  
    9.46  static void
    9.47 @@ -245,13 +225,12 @@
    9.48      }
    9.49  
    9.50      add_to_internal_dev_list(iscapture, devId);  /* new device, add it. */
    9.51 -    SDL_AudioDeviceConnected(iscapture, name);
    9.52 +    SDL_AddAudioDevice(iscapture, name, (void *) ((size_t) devId));
    9.53  }
    9.54  
    9.55 -static SDL_bool
    9.56 +static void
    9.57  reprocess_device_list(const int iscapture, AudioDeviceList **list)
    9.58  {
    9.59 -    SDL_bool was_disconnect = SDL_FALSE;
    9.60      AudioDeviceList *item;
    9.61      AudioDeviceList *prev = NULL;
    9.62      for (item = *list; item != NULL; item = item->next) {
    9.63 @@ -267,7 +246,7 @@
    9.64          if (item->alive) {
    9.65              prev = item;
    9.66          } else {
    9.67 -            was_disconnect = SDL_TRUE;
    9.68 +            SDL_RemoveAudioDevice((void *) ((size_t) item->devid));
    9.69              if (prev) {
    9.70                  prev->next = item->next;
    9.71              } else {
    9.72 @@ -277,88 +256,16 @@
    9.73          }
    9.74          item = next;
    9.75      }
    9.76 -
    9.77 -    return was_disconnect;
    9.78  }
    9.79  
    9.80 -
    9.81  /* this is called when the system's list of available audio devices changes. */
    9.82  static OSStatus
    9.83  device_list_changed(AudioObjectID systemObj, UInt32 num_addr, const AudioObjectPropertyAddress *addrs, void *data)
    9.84  {
    9.85 -    if (reprocess_device_list(SDL_TRUE, &capture_devs)) {
    9.86 -        SDL_AudioDeviceDisconnected(SDL_TRUE, NULL);
    9.87 -    }
    9.88 -
    9.89 -    if (reprocess_device_list(SDL_FALSE, &output_devs)) {
    9.90 -        SDL_AudioDeviceDisconnected(SDL_FALSE, NULL);
    9.91 -    }
    9.92 -
    9.93 +    reprocess_device_list(SDL_TRUE, &capture_devs);
    9.94 +    reprocess_device_list(SDL_FALSE, &output_devs);
    9.95      return 0;
    9.96  }
    9.97 -
    9.98 -static int
    9.99 -find_device_by_name(_THIS, const char *devname, int iscapture)
   9.100 -{
   9.101 -    AudioDeviceID devid = 0;
   9.102 -    OSStatus result = noErr;
   9.103 -    UInt32 size = 0;
   9.104 -    UInt32 alive = 0;
   9.105 -    pid_t pid = 0;
   9.106 -
   9.107 -    AudioObjectPropertyAddress addr = {
   9.108 -        0,
   9.109 -        kAudioObjectPropertyScopeGlobal,
   9.110 -        kAudioObjectPropertyElementMaster
   9.111 -    };
   9.112 -
   9.113 -    if (devname == NULL) {
   9.114 -        size = sizeof (AudioDeviceID);
   9.115 -        addr.mSelector =
   9.116 -            ((iscapture) ? kAudioHardwarePropertyDefaultInputDevice :
   9.117 -            kAudioHardwarePropertyDefaultOutputDevice);
   9.118 -        result = AudioObjectGetPropertyData(kAudioObjectSystemObject, &addr,
   9.119 -                                            0, NULL, &size, &devid);
   9.120 -        CHECK_RESULT("AudioHardwareGetProperty (default device)");
   9.121 -    } else {
   9.122 -        FindDevIdData data;
   9.123 -        SDL_zero(data);
   9.124 -        data.findname = devname;
   9.125 -        build_device_list(iscapture, findDevId, &data);
   9.126 -        if (!data.found) {
   9.127 -            SDL_SetError("CoreAudio: No such audio device.");
   9.128 -            return 0;
   9.129 -        }
   9.130 -        devid = data.devId;
   9.131 -    }
   9.132 -
   9.133 -    addr.mSelector = kAudioDevicePropertyDeviceIsAlive;
   9.134 -    addr.mScope = iscapture ? kAudioDevicePropertyScopeInput :
   9.135 -                    kAudioDevicePropertyScopeOutput;
   9.136 -
   9.137 -    size = sizeof (alive);
   9.138 -    result = AudioObjectGetPropertyData(devid, &addr, 0, NULL, &size, &alive);
   9.139 -    CHECK_RESULT
   9.140 -        ("AudioDeviceGetProperty (kAudioDevicePropertyDeviceIsAlive)");
   9.141 -
   9.142 -    if (!alive) {
   9.143 -        SDL_SetError("CoreAudio: requested device exists, but isn't alive.");
   9.144 -        return 0;
   9.145 -    }
   9.146 -
   9.147 -    addr.mSelector = kAudioDevicePropertyHogMode;
   9.148 -    size = sizeof (pid);
   9.149 -    result = AudioObjectGetPropertyData(devid, &addr, 0, NULL, &size, &pid);
   9.150 -
   9.151 -    /* some devices don't support this property, so errors are fine here. */
   9.152 -    if ((result == noErr) && (pid != -1)) {
   9.153 -        SDL_SetError("CoreAudio: requested device is being hogged.");
   9.154 -        return 0;
   9.155 -    }
   9.156 -
   9.157 -    this->hidden->deviceID = devid;
   9.158 -    return 1;
   9.159 -}
   9.160  #endif
   9.161  
   9.162  /* The CoreAudio callback */
   9.163 @@ -464,7 +371,7 @@
   9.164      }
   9.165  
   9.166      if (dead) {
   9.167 -        SDL_AudioDeviceDisconnected(this->iscapture, this);
   9.168 +        SDL_OpenedAudioDeviceDisconnected(this);
   9.169      }
   9.170  
   9.171      return 0;
   9.172 @@ -514,8 +421,63 @@
   9.173      }
   9.174  }
   9.175  
   9.176 +#if MACOSX_COREAUDIO
   9.177  static int
   9.178 -prepare_audiounit(_THIS, const char *devname, int iscapture,
   9.179 +prepare_device(_THIS, void *handle, int iscapture)
   9.180 +{
   9.181 +    AudioDeviceID devid = (AudioDeviceID) ((size_t) handle);
   9.182 +    OSStatus result = noErr;
   9.183 +    UInt32 size = 0;
   9.184 +    UInt32 alive = 0;
   9.185 +    pid_t pid = 0;
   9.186 +
   9.187 +    AudioObjectPropertyAddress addr = {
   9.188 +        0,
   9.189 +        kAudioObjectPropertyScopeGlobal,
   9.190 +        kAudioObjectPropertyElementMaster
   9.191 +    };
   9.192 +
   9.193 +    if (handle == NULL) {
   9.194 +        size = sizeof (AudioDeviceID);
   9.195 +        addr.mSelector =
   9.196 +            ((iscapture) ? kAudioHardwarePropertyDefaultInputDevice :
   9.197 +            kAudioHardwarePropertyDefaultOutputDevice);
   9.198 +        result = AudioObjectGetPropertyData(kAudioObjectSystemObject, &addr,
   9.199 +                                            0, NULL, &size, &devid);
   9.200 +        CHECK_RESULT("AudioHardwareGetProperty (default device)");
   9.201 +    }
   9.202 +
   9.203 +    addr.mSelector = kAudioDevicePropertyDeviceIsAlive;
   9.204 +    addr.mScope = iscapture ? kAudioDevicePropertyScopeInput :
   9.205 +                    kAudioDevicePropertyScopeOutput;
   9.206 +
   9.207 +    size = sizeof (alive);
   9.208 +    result = AudioObjectGetPropertyData(devid, &addr, 0, NULL, &size, &alive);
   9.209 +    CHECK_RESULT
   9.210 +        ("AudioDeviceGetProperty (kAudioDevicePropertyDeviceIsAlive)");
   9.211 +
   9.212 +    if (!alive) {
   9.213 +        SDL_SetError("CoreAudio: requested device exists, but isn't alive.");
   9.214 +        return 0;
   9.215 +    }
   9.216 +
   9.217 +    addr.mSelector = kAudioDevicePropertyHogMode;
   9.218 +    size = sizeof (pid);
   9.219 +    result = AudioObjectGetPropertyData(devid, &addr, 0, NULL, &size, &pid);
   9.220 +
   9.221 +    /* some devices don't support this property, so errors are fine here. */
   9.222 +    if ((result == noErr) && (pid != -1)) {
   9.223 +        SDL_SetError("CoreAudio: requested device is being hogged.");
   9.224 +        return 0;
   9.225 +    }
   9.226 +
   9.227 +    this->hidden->deviceID = devid;
   9.228 +    return 1;
   9.229 +}
   9.230 +#endif
   9.231 +
   9.232 +static int
   9.233 +prepare_audiounit(_THIS, void *handle, int iscapture,
   9.234                    const AudioStreamBasicDescription * strdesc)
   9.235  {
   9.236      OSStatus result = noErr;
   9.237 @@ -534,8 +496,7 @@
   9.238                                    kAudioUnitScope_Input);
   9.239  
   9.240  #if MACOSX_COREAUDIO
   9.241 -    if (!find_device_by_name(this, devname, iscapture)) {
   9.242 -        SDL_SetError("Couldn't find requested CoreAudio device");
   9.243 +    if (!prepare_device(this, handle, iscapture)) {
   9.244          return 0;
   9.245      }
   9.246  #endif
   9.247 @@ -623,7 +584,7 @@
   9.248  
   9.249  
   9.250  static int
   9.251 -COREAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
   9.252 +COREAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
   9.253  {
   9.254      AudioStreamBasicDescription strdesc;
   9.255      SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
   9.256 @@ -682,7 +643,7 @@
   9.257      strdesc.mBytesPerPacket =
   9.258          strdesc.mBytesPerFrame * strdesc.mFramesPerPacket;
   9.259  
   9.260 -    if (!prepare_audiounit(this, devname, iscapture, &strdesc)) {
   9.261 +    if (!prepare_audiounit(this, handle, iscapture, &strdesc)) {
   9.262          COREAUDIO_CloseDevice(this);
   9.263          return -1;      /* prepare_audiounit() will call SDL_SetError()... */
   9.264      }
    10.1 --- a/src/audio/directsound/SDL_directsound.c	Mon Mar 16 02:11:39 2015 -0400
    10.2 +++ b/src/audio/directsound/SDL_directsound.c	Wed Mar 18 02:01:17 2015 -0400
    10.3 @@ -144,15 +144,22 @@
    10.4      return SDL_SetError("%s", errbuf);
    10.5  }
    10.6  
    10.7 +static void
    10.8 +DSOUND_FreeDeviceHandle(void *handle)
    10.9 +{
   10.10 +    SDL_free(handle);
   10.11 +}
   10.12  
   10.13  static BOOL CALLBACK
   10.14  FindAllDevs(LPGUID guid, LPCWSTR desc, LPCWSTR module, LPVOID data)
   10.15  {
   10.16 -    SDL_AddAudioDevice addfn = (SDL_AddAudioDevice) data;
   10.17 +    const int iscapture = (int) ((size_t) data);
   10.18      if (guid != NULL) {  /* skip default device */
   10.19          char *str = WIN_StringToUTF8(desc);
   10.20          if (str != NULL) {
   10.21 -            addfn(str);
   10.22 +            LPGUID cpyguid = (LPGUID) SDL_malloc(sizeof (GUID));
   10.23 +            SDL_memcpy(cpyguid, guid, sizeof (GUID));
   10.24 +            SDL_AddAudioDevice(iscapture, str, cpyguid);
   10.25              SDL_free(str);  /* addfn() makes a copy of this string. */
   10.26          }
   10.27      }
   10.28 @@ -160,13 +167,10 @@
   10.29  }
   10.30  
   10.31  static void
   10.32 -DSOUND_DetectDevices(int iscapture, SDL_AddAudioDevice addfn)
   10.33 +DSOUND_DetectDevices(void)
   10.34  {
   10.35 -    if (iscapture) {
   10.36 -        pDirectSoundCaptureEnumerateW(FindAllDevs, addfn);
   10.37 -    } else {
   10.38 -        pDirectSoundEnumerateW(FindAllDevs, addfn);
   10.39 -    }
   10.40 +    pDirectSoundCaptureEnumerateW(FindAllDevs, (void *) ((size_t) 1));
   10.41 +    pDirectSoundEnumerateW(FindAllDevs, (void *) ((size_t) 0));
   10.42  }
   10.43  
   10.44  
   10.45 @@ -419,53 +423,14 @@
   10.46      return (numchunks);
   10.47  }
   10.48  
   10.49 -typedef struct FindDevGUIDData
   10.50 -{
   10.51 -    const char *devname;
   10.52 -    GUID guid;
   10.53 -    int found;
   10.54 -} FindDevGUIDData;
   10.55 -
   10.56 -static BOOL CALLBACK
   10.57 -FindDevGUID(LPGUID guid, LPCWSTR desc, LPCWSTR module, LPVOID _data)
   10.58 -{
   10.59 -    if (guid != NULL) {  /* skip the default device. */
   10.60 -        FindDevGUIDData *data = (FindDevGUIDData *) _data;
   10.61 -        char *str = WIN_StringToUTF8(desc);
   10.62 -        const int match = (SDL_strcmp(str, data->devname) == 0);
   10.63 -        SDL_free(str);
   10.64 -        if (match) {
   10.65 -            data->found = 1;
   10.66 -            SDL_memcpy(&data->guid, guid, sizeof (data->guid));
   10.67 -            return FALSE;  /* found it! stop enumerating. */
   10.68 -        }
   10.69 -    }
   10.70 -    return TRUE;  /* keep enumerating. */
   10.71 -}
   10.72 -
   10.73  static int
   10.74 -DSOUND_OpenDevice(_THIS, const char *devname, int iscapture)
   10.75 +DSOUND_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
   10.76  {
   10.77      HRESULT result;
   10.78      SDL_bool valid_format = SDL_FALSE;
   10.79      SDL_bool tried_format = SDL_FALSE;
   10.80      SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
   10.81 -    FindDevGUIDData devguid;
   10.82 -    LPGUID guid = NULL;
   10.83 -
   10.84 -    if (devname != NULL) {
   10.85 -        devguid.found = 0;
   10.86 -        devguid.devname = devname;
   10.87 -        if (iscapture)
   10.88 -            pDirectSoundCaptureEnumerateW(FindDevGUID, &devguid);
   10.89 -        else
   10.90 -            pDirectSoundEnumerateW(FindDevGUID, &devguid);
   10.91 -
   10.92 -        if (!devguid.found) {
   10.93 -            return SDL_SetError("DirectSound: Requested device not found");
   10.94 -        }
   10.95 -        guid = &devguid.guid;
   10.96 -    }
   10.97 +    LPGUID guid = (LPGUID) handle;
   10.98  
   10.99      /* Initialize all variables that we clean on shutdown */
  10.100      this->hidden = (struct SDL_PrivateAudioData *)
  10.101 @@ -536,6 +501,8 @@
  10.102      impl->WaitDone = DSOUND_WaitDone;
  10.103      impl->GetDeviceBuf = DSOUND_GetDeviceBuf;
  10.104      impl->CloseDevice = DSOUND_CloseDevice;
  10.105 +    impl->FreeDeviceHandle = DSOUND_FreeDeviceHandle;
  10.106 +
  10.107      impl->Deinitialize = DSOUND_Deinitialize;
  10.108  
  10.109      return 1;   /* this audio target is available. */
    11.1 --- a/src/audio/disk/SDL_diskaudio.c	Mon Mar 16 02:11:39 2015 -0400
    11.2 +++ b/src/audio/disk/SDL_diskaudio.c	Wed Mar 18 02:01:17 2015 -0400
    11.3 @@ -71,7 +71,7 @@
    11.4  
    11.5      /* If we couldn't write, assume fatal error for now */
    11.6      if (written != this->hidden->mixlen) {
    11.7 -        SDL_AudioDeviceDisconnected(SDL_FALSE, this);
    11.8 +        SDL_OpenedAudioDeviceDisconnected(this);
    11.9      }
   11.10  #ifdef DEBUG_AUDIO
   11.11      fprintf(stderr, "Wrote %d bytes of audio data\n", written);
   11.12 @@ -100,7 +100,7 @@
   11.13  }
   11.14  
   11.15  static int
   11.16 -DISKAUD_OpenDevice(_THIS, const char *devname, int iscapture)
   11.17 +DISKAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
   11.18  {
   11.19      const char *envr = SDL_getenv(DISKENVR_WRITEDELAY);
   11.20      const char *fname = DISKAUD_GetOutputFilename(devname);
   11.21 @@ -151,6 +151,8 @@
   11.22      impl->GetDeviceBuf = DISKAUD_GetDeviceBuf;
   11.23      impl->CloseDevice = DISKAUD_CloseDevice;
   11.24  
   11.25 +    impl->AllowsArbitraryDeviceNames = 1;
   11.26 +
   11.27      return 1;   /* this audio target is available. */
   11.28  }
   11.29  
    12.1 --- a/src/audio/dsp/SDL_dspaudio.c	Mon Mar 16 02:11:39 2015 -0400
    12.2 +++ b/src/audio/dsp/SDL_dspaudio.c	Wed Mar 18 02:01:17 2015 -0400
    12.3 @@ -51,9 +51,9 @@
    12.4  
    12.5  
    12.6  static void
    12.7 -DSP_DetectDevices(int iscapture, SDL_AddAudioDevice addfn)
    12.8 +DSP_DetectDevices(void)
    12.9  {
   12.10 -    SDL_EnumUnixAudioDevices(iscapture, 0, NULL, addfn);
   12.11 +    SDL_EnumUnixAudioDevices(0, NULL);
   12.12  }
   12.13  
   12.14  
   12.15 @@ -74,7 +74,7 @@
   12.16  
   12.17  
   12.18  static int
   12.19 -DSP_OpenDevice(_THIS, const char *devname, int iscapture)
   12.20 +DSP_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
   12.21  {
   12.22      const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT);
   12.23      int format;
   12.24 @@ -270,7 +270,7 @@
   12.25      const int mixlen = this->hidden->mixlen;
   12.26      if (write(this->hidden->audio_fd, mixbuf, mixlen) == -1) {
   12.27          perror("Audio write");
   12.28 -        SDL_AudioDeviceDisconnected(SDL_FALSE, this);
   12.29 +        SDL_OpenedAudioDeviceDisconnected(this);
   12.30      }
   12.31  #ifdef DEBUG_AUDIO
   12.32      fprintf(stderr, "Wrote %d bytes of audio data\n", mixlen);
   12.33 @@ -293,6 +293,8 @@
   12.34      impl->GetDeviceBuf = DSP_GetDeviceBuf;
   12.35      impl->CloseDevice = DSP_CloseDevice;
   12.36  
   12.37 +    impl->AllowsArbitraryDeviceNames = 1;
   12.38 +
   12.39      return 1;   /* this audio target is available. */
   12.40  }
   12.41  
    13.1 --- a/src/audio/dummy/SDL_dummyaudio.c	Mon Mar 16 02:11:39 2015 -0400
    13.2 +++ b/src/audio/dummy/SDL_dummyaudio.c	Wed Mar 18 02:01:17 2015 -0400
    13.3 @@ -27,7 +27,7 @@
    13.4  #include "SDL_dummyaudio.h"
    13.5  
    13.6  static int
    13.7 -DUMMYAUD_OpenDevice(_THIS, const char *devname, int iscapture)
    13.8 +DUMMYAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
    13.9  {
   13.10      return 0;                   /* always succeeds. */
   13.11  }
    14.1 --- a/src/audio/emscripten/SDL_emscriptenaudio.c	Mon Mar 16 02:11:39 2015 -0400
    14.2 +++ b/src/audio/emscripten/SDL_emscriptenaudio.c	Wed Mar 18 02:01:17 2015 -0400
    14.3 @@ -151,7 +151,7 @@
    14.4  }
    14.5  
    14.6  static int
    14.7 -Emscripten_OpenDevice(_THIS, const char *devname, int iscapture)
    14.8 +Emscripten_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
    14.9  {
   14.10      SDL_bool valid_format = SDL_FALSE;
   14.11      SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
    15.1 --- a/src/audio/esd/SDL_esdaudio.c	Mon Mar 16 02:11:39 2015 -0400
    15.2 +++ b/src/audio/esd/SDL_esdaudio.c	Wed Mar 18 02:01:17 2015 -0400
    15.3 @@ -129,7 +129,7 @@
    15.4          /* Check every 10 loops */
    15.5          if (this->hidden->parent && (((++cnt) % 10) == 0)) {
    15.6              if (kill(this->hidden->parent, 0) < 0 && errno == ESRCH) {
    15.7 -                SDL_AudioDeviceDisconnected(SDL_FALSE, this);
    15.8 +                SDL_OpenedAudioDeviceDisconnected(this);
    15.9              }
   15.10          }
   15.11      }
   15.12 @@ -161,7 +161,7 @@
   15.13  
   15.14      /* If we couldn't write, assume fatal error for now */
   15.15      if (written < 0) {
   15.16 -        SDL_AudioDeviceDisconnected(SDL_FALSE, this);
   15.17 +        SDL_OpenedAudioDeviceDisconnected(this);
   15.18      }
   15.19  }
   15.20  
   15.21 @@ -215,7 +215,7 @@
   15.22  
   15.23  
   15.24  static int
   15.25 -ESD_OpenDevice(_THIS, const char *devname, int iscapture)
   15.26 +ESD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
   15.27  {
   15.28      esd_format_t format = (ESD_STREAM | ESD_PLAY);
   15.29      SDL_AudioFormat test_format = 0;
    16.1 --- a/src/audio/fusionsound/SDL_fsaudio.c	Mon Mar 16 02:11:39 2015 -0400
    16.2 +++ b/src/audio/fusionsound/SDL_fsaudio.c	Wed Mar 18 02:01:17 2015 -0400
    16.3 @@ -143,7 +143,7 @@
    16.4                                        this->hidden->mixsamples);
    16.5      /* If we couldn't write, assume fatal error for now */
    16.6      if (ret) {
    16.7 -        SDL_AudioDeviceDisconnected(SDL_FALSE, this);
    16.8 +        SDL_OpenedAudioDeviceDisconnected(this);
    16.9      }
   16.10  #ifdef DEBUG_AUDIO
   16.11      fprintf(stderr, "Wrote %d bytes of audio data\n", this->hidden->mixlen);
   16.12 @@ -186,7 +186,7 @@
   16.13  
   16.14  
   16.15  static int
   16.16 -SDL_FS_OpenDevice(_THIS, const char *devname, int iscapture)
   16.17 +SDL_FS_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
   16.18  {
   16.19      int bytes;
   16.20      SDL_AudioFormat test_format = 0, format = 0;
    17.1 --- a/src/audio/haiku/SDL_haikuaudio.cc	Mon Mar 16 02:11:39 2015 -0400
    17.2 +++ b/src/audio/haiku/SDL_haikuaudio.cc	Wed Mar 18 02:01:17 2015 -0400
    17.3 @@ -111,7 +111,7 @@
    17.4  
    17.5  
    17.6  static int
    17.7 -HAIKUAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
    17.8 +HAIKUAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
    17.9  {
   17.10      int valid_datatype = 0;
   17.11      media_raw_audio_format format;
    18.1 --- a/src/audio/nacl/SDL_naclaudio.c	Mon Mar 16 02:11:39 2015 -0400
    18.2 +++ b/src/audio/nacl/SDL_naclaudio.c	Wed Mar 18 02:01:17 2015 -0400
    18.3 @@ -43,7 +43,7 @@
    18.4  #define SAMPLE_FRAME_COUNT 4096
    18.5  
    18.6  /* Audio driver functions */
    18.7 -static int NACLAUD_OpenDevice(_THIS, const char *devname, int iscapture);
    18.8 +static int NACLAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture);
    18.9  static void NACLAUD_CloseDevice(_THIS);
   18.10  static void nacl_audio_callback(void* samples, uint32_t buffer_size, PP_TimeDelta latency, void* data);
   18.11  
   18.12 @@ -85,7 +85,7 @@
   18.13  }
   18.14  
   18.15  static int
   18.16 -NACLAUD_OpenDevice(_THIS, const char *devname, int iscapture) {
   18.17 +NACLAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) {
   18.18      PP_Instance instance = PSGetInstanceId();
   18.19      const PPB_Audio *ppb_audio = PSInterfaceAudio();
   18.20      const PPB_AudioConfig *ppb_audiocfg = PSInterfaceAudioConfig();
   18.21 @@ -130,9 +130,7 @@
   18.22      /* Set the function pointers */
   18.23      impl->OpenDevice = NACLAUD_OpenDevice;
   18.24      impl->CloseDevice = NACLAUD_CloseDevice;
   18.25 -    impl->HasCaptureSupport = 0;
   18.26      impl->OnlyHasDefaultOutputDevice = 1;
   18.27 -    impl->OnlyHasDefaultInputDevice = 1;
   18.28      impl->ProvidesOwnCallbackThread = 1;
   18.29      /*
   18.30       *    impl->WaitDevice = NACLAUD_WaitDevice;
    19.1 --- a/src/audio/nas/SDL_nasaudio.c	Mon Mar 16 02:11:39 2015 -0400
    19.2 +++ b/src/audio/nas/SDL_nasaudio.c	Wed Mar 18 02:01:17 2015 -0400
    19.3 @@ -276,7 +276,7 @@
    19.4  }
    19.5  
    19.6  static int
    19.7 -NAS_OpenDevice(_THIS, const char *devname, int iscapture)
    19.8 +NAS_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
    19.9  {
   19.10      AuElement elms[3];
   19.11      int buffer_size;
    20.1 --- a/src/audio/paudio/SDL_paudio.c	Mon Mar 16 02:11:39 2015 -0400
    20.2 +++ b/src/audio/paudio/SDL_paudio.c	Wed Mar 18 02:01:17 2015 -0400
    20.3 @@ -176,7 +176,7 @@
    20.4               * the user know what happened.
    20.5               */
    20.6              fprintf(stderr, "SDL: %s - %s\n", strerror(errno), message);
    20.7 -            SDL_AudioDeviceDisconnected(SDL_FALSE, this);
    20.8 +            SDL_OpenedAudioDeviceDisconnected(this);
    20.9              /* Don't try to close - may hang */
   20.10              this->hidden->audio_fd = -1;
   20.11  #ifdef DEBUG_AUDIO
   20.12 @@ -212,7 +212,7 @@
   20.13  
   20.14      /* If we couldn't write, assume fatal error for now */
   20.15      if (written < 0) {
   20.16 -        SDL_AudioDeviceDisconnected(SDL_FALSE, this);
   20.17 +        SDL_OpenedAudioDeviceDisconnected(this);
   20.18      }
   20.19  #ifdef DEBUG_AUDIO
   20.20      fprintf(stderr, "Wrote %d bytes of audio data\n", written);
   20.21 @@ -241,7 +241,7 @@
   20.22  }
   20.23  
   20.24  static int
   20.25 -PAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
   20.26 +PAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
   20.27  {
   20.28      const char *workaround = SDL_getenv("SDL_DSP_NOSELECT");
   20.29      char audiodev[1024];
    21.1 --- a/src/audio/psp/SDL_pspaudio.c	Mon Mar 16 02:11:39 2015 -0400
    21.2 +++ b/src/audio/psp/SDL_pspaudio.c	Wed Mar 18 02:01:17 2015 -0400
    21.3 @@ -43,7 +43,7 @@
    21.4  #define PSPAUD_DRIVER_NAME         "psp"
    21.5  
    21.6  static int
    21.7 -PSPAUD_OpenDevice(_THIS, const char *devname, int iscapture)
    21.8 +PSPAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
    21.9  {
   21.10      int format, mixlen, i;
   21.11      this->hidden = (struct SDL_PrivateAudioData *)
    22.1 --- a/src/audio/pulseaudio/SDL_pulseaudio.c	Mon Mar 16 02:11:39 2015 -0400
    22.2 +++ b/src/audio/pulseaudio/SDL_pulseaudio.c	Wed Mar 18 02:01:17 2015 -0400
    22.3 @@ -302,7 +302,7 @@
    22.4          if (PULSEAUDIO_pa_context_get_state(h->context) != PA_CONTEXT_READY ||
    22.5              PULSEAUDIO_pa_stream_get_state(h->stream) != PA_STREAM_READY ||
    22.6              PULSEAUDIO_pa_mainloop_iterate(h->mainloop, 1, NULL) < 0) {
    22.7 -            SDL_AudioDeviceDisconnected(SDL_FALSE, this);
    22.8 +            SDL_OpenedAudioDeviceDisconnected(this);
    22.9              return;
   22.10          }
   22.11          if (PULSEAUDIO_pa_stream_writable_size(h->stream) >= h->mixlen) {
   22.12 @@ -318,7 +318,7 @@
   22.13      struct SDL_PrivateAudioData *h = this->hidden;
   22.14      if (PULSEAUDIO_pa_stream_write(h->stream, h->mixbuf, h->mixlen, NULL, 0LL,
   22.15                                     PA_SEEK_RELATIVE) < 0) {
   22.16 -        SDL_AudioDeviceDisconnected(SDL_FALSE, this);
   22.17 +        SDL_OpenedAudioDeviceDisconnected(this);
   22.18      }
   22.19  }
   22.20  
   22.21 @@ -378,7 +378,7 @@
   22.22  }
   22.23  
   22.24  static int
   22.25 -PULSEAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
   22.26 +PULSEAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
   22.27  {
   22.28      struct SDL_PrivateAudioData *h = NULL;
   22.29      Uint16 test_format = 0;
    23.1 --- a/src/audio/qsa/SDL_qsa_audio.c	Mon Mar 16 02:11:39 2015 -0400
    23.2 +++ b/src/audio/qsa/SDL_qsa_audio.c	Wed Mar 18 02:01:17 2015 -0400
    23.3 @@ -19,6 +19,15 @@
    23.4    3. This notice may not be removed or altered from any source distribution.
    23.5  */
    23.6  
    23.7 +/*
    23.8 + * !!! FIXME: streamline this a little by removing all the
    23.9 + * !!! FIXME:  if (capture) {} else {} sections that are identical
   23.10 + * !!! FIXME:  except for one flag.
   23.11 + */
   23.12 +
   23.13 +/* !!! FIXME: can this target support hotplugging? */
   23.14 +/* !!! FIXME: ...does SDL2 even support QNX? */
   23.15 +
   23.16  #include "../../SDL_internal.h"
   23.17  
   23.18  #if SDL_AUDIO_DRIVER_QSA
   23.19 @@ -300,7 +309,7 @@
   23.20  
   23.21      /* If we couldn't write, assume fatal error for now */
   23.22      if (towrite != 0) {
   23.23 -        SDL_AudioDeviceDisconnected(SDL_FALSE, this);
   23.24 +        SDL_OpenedAudioDeviceDisconnected(this);
   23.25      }
   23.26  }
   23.27  
   23.28 @@ -337,8 +346,9 @@
   23.29  }
   23.30  
   23.31  static int
   23.32 -QSA_OpenDevice(_THIS, const char *devname, int iscapture)
   23.33 +QSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
   23.34  {
   23.35 +    const QSA_Device *device = (const QSA_Device *) handle;
   23.36      int status = 0;
   23.37      int format = 0;
   23.38      SDL_AudioFormat test_format = 0;
   23.39 @@ -363,80 +373,19 @@
   23.40      /* Initialize channel direction: capture or playback */
   23.41      this->hidden->iscapture = iscapture;
   23.42  
   23.43 -    /* Find deviceid and cardid by device name for playback */
   23.44 -    if ((!this->hidden->iscapture) && (devname != NULL)) {
   23.45 -        uint32_t device;
   23.46 -        int32_t status;
   23.47 -
   23.48 -        /* Search in the playback devices */
   23.49 -        device = 0;
   23.50 -        do {
   23.51 -            status = SDL_strcmp(qsa_playback_device[device].name, devname);
   23.52 -            if (status == 0) {
   23.53 -                /* Found requested device */
   23.54 -                this->hidden->deviceno = qsa_playback_device[device].deviceno;
   23.55 -                this->hidden->cardno = qsa_playback_device[device].cardno;
   23.56 -                break;
   23.57 -            }
   23.58 -            device++;
   23.59 -            if (device >= qsa_playback_devices) {
   23.60 -                QSA_CloseDevice(this);
   23.61 -                return SDL_SetError("No such playback device");
   23.62 -            }
   23.63 -        } while (1);
   23.64 -    }
   23.65 -
   23.66 -    /* Find deviceid and cardid by device name for capture */
   23.67 -    if ((this->hidden->iscapture) && (devname != NULL)) {
   23.68 -        /* Search in the capture devices */
   23.69 -        uint32_t device;
   23.70 -        int32_t status;
   23.71 -
   23.72 -        /* Searching in the playback devices */
   23.73 -        device = 0;
   23.74 -        do {
   23.75 -            status = SDL_strcmp(qsa_capture_device[device].name, devname);
   23.76 -            if (status == 0) {
   23.77 -                /* Found requested device */
   23.78 -                this->hidden->deviceno = qsa_capture_device[device].deviceno;
   23.79 -                this->hidden->cardno = qsa_capture_device[device].cardno;
   23.80 -                break;
   23.81 -            }
   23.82 -            device++;
   23.83 -            if (device >= qsa_capture_devices) {
   23.84 -                QSA_CloseDevice(this);
   23.85 -                return SDL_SetError("No such capture device");
   23.86 -            }
   23.87 -        } while (1);
   23.88 -    }
   23.89 -
   23.90 -    /* Check if SDL requested default audio device */
   23.91 -    if (devname == NULL) {
   23.92 +    if (device != NULL) {
   23.93 +        /* Open requested audio device */
   23.94 +        this->hidden->deviceno = device->deviceno;
   23.95 +        this->hidden->cardno = device->cardno;
   23.96 +        status = snd_pcm_open(&this->hidden->audio_handle,
   23.97 +                              device->cardno, device->deviceno,
   23.98 +                              iscapture ? SND_PCM_OPEN_PLAYBACK : SND_PCM_OPEN_CAPTURE);
   23.99 +    } else {
  23.100          /* Open system default audio device */
  23.101 -        if (!this->hidden->iscapture) {
  23.102 -            status = snd_pcm_open_preferred(&this->hidden->audio_handle,
  23.103 -                                            &this->hidden->cardno,
  23.104 -                                            &this->hidden->deviceno,
  23.105 -                                            SND_PCM_OPEN_PLAYBACK);
  23.106 -        } else {
  23.107 -            status = snd_pcm_open_preferred(&this->hidden->audio_handle,
  23.108 -                                            &this->hidden->cardno,
  23.109 -                                            &this->hidden->deviceno,
  23.110 -                                            SND_PCM_OPEN_CAPTURE);
  23.111 -        }
  23.112 -    } else {
  23.113 -        /* Open requested audio device */
  23.114 -        if (!this->hidden->iscapture) {
  23.115 -            status =
  23.116 -                snd_pcm_open(&this->hidden->audio_handle,
  23.117 -                             this->hidden->cardno, this->hidden->deviceno,
  23.118 -                             SND_PCM_OPEN_PLAYBACK);
  23.119 -        } else {
  23.120 -            status =
  23.121 -                snd_pcm_open(&this->hidden->audio_handle,
  23.122 -                             this->hidden->cardno, this->hidden->deviceno,
  23.123 -                             SND_PCM_OPEN_CAPTURE);
  23.124 -        }
  23.125 +        status = snd_pcm_open_preferred(&this->hidden->audio_handle,
  23.126 +                                        &this->hidden->cardno,
  23.127 +                                        &this->hidden->deviceno,
  23.128 +                                        iscapture ? SND_PCM_OPEN_PLAYBACK : SND_PCM_OPEN_CAPTURE);
  23.129      }
  23.130  
  23.131      /* Check if requested device is opened */
  23.132 @@ -638,7 +587,7 @@
  23.133  }
  23.134  
  23.135  static void
  23.136 -QSA_DetectDevices(int iscapture, SDL_AddAudioDevice addfn)
  23.137 +QSA_DetectDevices(void)
  23.138  {
  23.139      uint32_t it;
  23.140      uint32_t cards;
  23.141 @@ -656,8 +605,9 @@
  23.142          return;
  23.143      }
  23.144  
  23.145 +    /* !!! FIXME: code duplication */
  23.146      /* Find requested devices by type */
  23.147 -    if (!iscapture) {
  23.148 +    {  /* output devices */
  23.149          /* Playback devices enumeration requested */
  23.150          for (it = 0; it < cards; it++) {
  23.151              devices = 0;
  23.152 @@ -688,7 +638,7 @@
  23.153                              devices;
  23.154                          status = snd_pcm_close(handle);
  23.155                          if (status == EOK) {
  23.156 -                            addfn(qsa_playback_device[qsa_playback_devices].name);
  23.157 +                            SDL_AddAudioDevice(SDL_FALSE, qsa_playback_device[qsa_playback_devices].name, &qsa_playback_device[qsa_playback_devices]);
  23.158                              qsa_playback_devices++;
  23.159                          }
  23.160                      } else {
  23.161 @@ -713,7 +663,9 @@
  23.162                  break;
  23.163              }
  23.164          }
  23.165 -    } else {
  23.166 +    }
  23.167 +
  23.168 +    {  /* capture devices */
  23.169          /* Capture devices enumeration requested */
  23.170          for (it = 0; it < cards; it++) {
  23.171              devices = 0;
  23.172 @@ -744,7 +696,7 @@
  23.173                              devices;
  23.174                          status = snd_pcm_close(handle);
  23.175                          if (status == EOK) {
  23.176 -                            addfn(qsa_capture_device[qsa_capture_devices].name);
  23.177 +                            SDL_AddAudioDevice(SDL_TRUE, qsa_capture_device[qsa_capture_devices].name, &qsa_capture_device[qsa_capture_devices]);
  23.178                              qsa_capture_devices++;
  23.179                          }
  23.180                      } else {
    24.1 --- a/src/audio/sndio/SDL_sndioaudio.c	Mon Mar 16 02:11:39 2015 -0400
    24.2 +++ b/src/audio/sndio/SDL_sndioaudio.c	Wed Mar 18 02:01:17 2015 -0400
    24.3 @@ -158,7 +158,7 @@
    24.4  
    24.5      /* If we couldn't write, assume fatal error for now */
    24.6      if ( written == 0 ) {
    24.7 -        SDL_AudioDeviceDisconnected(SDL_FALSE, this);
    24.8 +        SDL_OpenedAudioDeviceDisconnected(this);
    24.9      }
   24.10  #ifdef DEBUG_AUDIO
   24.11      fprintf(stderr, "Wrote %d bytes of audio data\n", written);
   24.12 @@ -193,7 +193,7 @@
   24.13  }
   24.14  
   24.15  static int
   24.16 -SNDIO_OpenDevice(_THIS, const char *devname, int iscapture)
   24.17 +SNDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
   24.18  {
   24.19      SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
   24.20      struct sio_par par;
    25.1 --- a/src/audio/sun/SDL_sunaudio.c	Mon Mar 16 02:11:39 2015 -0400
    25.2 +++ b/src/audio/sun/SDL_sunaudio.c	Wed Mar 18 02:01:17 2015 -0400
    25.3 @@ -56,9 +56,9 @@
    25.4  
    25.5  /* Audio driver bootstrap functions */
    25.6  static void
    25.7 -SUNAUDIO_DetectDevices(int iscapture, SDL_AddAudioDevice addfn)
    25.8 +SUNAUDIO_DetectDevices(void)
    25.9  {
   25.10 -    SDL_EnumUnixAudioDevices(iscapture, 1, (int (*)(int fd)) NULL, addfn);
   25.11 +    SDL_EnumUnixAudioDevices(1, (int (*)(int)) NULL);
   25.12  }
   25.13  
   25.14  #ifdef DEBUG_AUDIO
   25.15 @@ -158,7 +158,7 @@
   25.16          if (write(this->hidden->audio_fd, this->hidden->ulaw_buf,
   25.17              this->hidden->fragsize) < 0) {
   25.18              /* Assume fatal error, for now */
   25.19 -            SDL_AudioDeviceDisconnected(SDL_FALSE, this);
   25.20 +            SDL_OpenedAudioDeviceDisconnected(this);
   25.21          }
   25.22          this->hidden->written += this->hidden->fragsize;
   25.23      } else {
   25.24 @@ -168,7 +168,7 @@
   25.25          if (write(this->hidden->audio_fd, this->hidden->mixbuf,
   25.26              this->spec.size) < 0) {
   25.27              /* Assume fatal error, for now */
   25.28 -            SDL_AudioDeviceDisconnected(SDL_FALSE, this);
   25.29 +            SDL_OpenedAudioDeviceDisconnected(this);
   25.30          }
   25.31          this->hidden->written += this->hidden->fragsize;
   25.32      }
   25.33 @@ -198,7 +198,7 @@
   25.34  }
   25.35  
   25.36  static int
   25.37 -SUNAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
   25.38 +SUNAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
   25.39  {
   25.40      const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT);
   25.41      SDL_AudioFormat format = 0;
   25.42 @@ -414,6 +414,8 @@
   25.43      impl->GetDeviceBuf = SUNAUDIO_GetDeviceBuf;
   25.44      impl->CloseDevice = SUNAUDIO_CloseDevice;
   25.45  
   25.46 +    impl->AllowsArbitraryDeviceNames = 1;
   25.47 +
   25.48      return 1; /* this audio target is available. */
   25.49  }
   25.50  
    26.1 --- a/src/audio/winmm/SDL_winmm.c	Mon Mar 16 02:11:39 2015 -0400
    26.2 +++ b/src/audio/winmm/SDL_winmm.c	Wed Mar 18 02:01:17 2015 -0400
    26.3 @@ -36,8 +36,10 @@
    26.4  #define WAVE_FORMAT_IEEE_FLOAT 0x0003
    26.5  #endif
    26.6  
    26.7 -#define DETECT_DEV_IMPL(typ, capstyp) \
    26.8 -static void DetectWave##typ##Devs(SDL_AddAudioDevice addfn) { \
    26.9 +#define DETECT_DEV_IMPL(iscap, typ, capstyp) \
   26.10 +static void DetectWave##typ##Devs(void) { \
   26.11 +    const UINT iscapture = iscap ? 1 : 0; \
   26.12 +    UINT devcount = wave##typ##GetNumDevs(); \
   26.13      const UINT devcount = wave##typ##GetNumDevs(); \
   26.14      capstyp caps; \
   26.15      UINT i; \
   26.16 @@ -45,24 +47,21 @@
   26.17          if (wave##typ##GetDevCaps(i,&caps,sizeof(caps))==MMSYSERR_NOERROR) { \
   26.18              char *name = WIN_StringToUTF8(caps.szPname); \
   26.19              if (name != NULL) { \
   26.20 -                addfn(name); \
   26.21 +                SDL_AddAudioDevice((int) iscapture, name, (void *) ((size_t) i|(iscap<<31))); \
   26.22                  SDL_free(name); \
   26.23              } \
   26.24          } \
   26.25      } \
   26.26  }
   26.27  
   26.28 -DETECT_DEV_IMPL(Out, WAVEOUTCAPS)
   26.29 -DETECT_DEV_IMPL(In, WAVEINCAPS)
   26.30 +DETECT_DEV_IMPL(SDL_FALSE, Out, WAVEOUTCAPS)
   26.31 +DETECT_DEV_IMPL(SDL_TRUE, In, WAVEINCAPS)
   26.32  
   26.33  static void
   26.34 -WINMM_DetectDevices(int iscapture, SDL_AddAudioDevice addfn)
   26.35 +WINMM_DetectDevices()
   26.36  {
   26.37 -    if (iscapture) {
   26.38 -        DetectWaveInDevs(addfn);
   26.39 -    } else {
   26.40 -        DetectWaveOutDevs(addfn);
   26.41 -    }
   26.42 +    DetectWaveInDevs();
   26.43 +    DetectWaveOutDevs();
   26.44  }
   26.45  
   26.46  static void CALLBACK
   26.47 @@ -220,7 +219,7 @@
   26.48  }
   26.49  
   26.50  static int
   26.51 -WINMM_OpenDevice(_THIS, const char *devname, int iscapture)
   26.52 +WINMM_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
   26.53  {
   26.54      SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
   26.55      int valid_datatype = 0;
   26.56 @@ -230,37 +229,13 @@
   26.57      char *utf8 = NULL;
   26.58      UINT i;
   26.59  
   26.60 -    if (devname != NULL) {  /* specific device requested? */
   26.61 +    if (handle != NULL) {  /* specific device requested? */
   26.62 +        const size_t val = (size_t) handle;
   26.63 +        devId = (UINT) val;
   26.64          if (iscapture) {
   26.65 -            const UINT devcount = waveInGetNumDevs();
   26.66 -            WAVEINCAPS caps;
   26.67 -            for (i = 0; (i < devcount) && (devId == WAVE_MAPPER); i++) {
   26.68 -                result = waveInGetDevCaps(i, &caps, sizeof (caps));
   26.69 -                if (result != MMSYSERR_NOERROR)
   26.70 -                    continue;
   26.71 -                else if ((utf8 = WIN_StringToUTF8(caps.szPname)) == NULL)
   26.72 -                    continue;
   26.73 -                else if (SDL_strcmp(devname, utf8) == 0)
   26.74 -                    devId = i;
   26.75 -                SDL_free(utf8);
   26.76 -            }
   26.77 -        } else {
   26.78 -            const UINT devcount = waveOutGetNumDevs();
   26.79 -            WAVEOUTCAPS caps;
   26.80 -            for (i = 0; (i < devcount) && (devId == WAVE_MAPPER); i++) {
   26.81 -                result = waveOutGetDevCaps(i, &caps, sizeof (caps));
   26.82 -                if (result != MMSYSERR_NOERROR)
   26.83 -                    continue;
   26.84 -                else if ((utf8 = WIN_StringToUTF8(caps.szPname)) == NULL)
   26.85 -                    continue;
   26.86 -                else if (SDL_strcmp(devname, utf8) == 0)
   26.87 -                    devId = i;
   26.88 -                SDL_free(utf8);
   26.89 -            }
   26.90 -        }
   26.91 -
   26.92 -        if (devId == WAVE_MAPPER) {
   26.93 -            return SDL_SetError("Requested device not found");
   26.94 +            /* we use the top bit to make value unique vs output indices. */
   26.95 +            SDL_assert((devId & (1<<31)) != 0);
   26.96 +            devId &= ~(1<<31);
   26.97          }
   26.98      }
   26.99  
    27.1 --- a/src/audio/xaudio2/SDL_xaudio2.c	Mon Mar 16 02:11:39 2015 -0400
    27.2 +++ b/src/audio/xaudio2/SDL_xaudio2.c	Wed Mar 18 02:01:17 2015 -0400
    27.3 @@ -126,16 +126,13 @@
    27.4  
    27.5  
    27.6  static void
    27.7 -XAUDIO2_DetectDevices(int iscapture, SDL_AddAudioDevice addfn)
    27.8 +XAUDIO2_DetectDevices(void)
    27.9  {
   27.10      IXAudio2 *ixa2 = NULL;
   27.11      UINT32 devcount = 0;
   27.12      UINT32 i = 0;
   27.13  
   27.14 -    if (iscapture) {
   27.15 -        SDL_SetError("XAudio2: capture devices unsupported.");
   27.16 -        return;
   27.17 -    } else if (XAudio2Create(&ixa2, 0, XAUDIO2_DEFAULT_PROCESSOR) != S_OK) {
   27.18 +    if (XAudio2Create(&ixa2, 0, XAUDIO2_DEFAULT_PROCESSOR) != S_OK) {
   27.19          SDL_SetError("XAudio2: XAudio2Create() failed at detection.");
   27.20          return;
   27.21      } else if (IXAudio2_GetDeviceCount(ixa2, &devcount) != S_OK) {
   27.22 @@ -149,8 +146,8 @@
   27.23          if (IXAudio2_GetDeviceDetails(ixa2, i, &details) == S_OK) {
   27.24              char *str = WIN_StringToUTF8(details.DisplayName);
   27.25              if (str != NULL) {
   27.26 -                addfn(str);
   27.27 -                SDL_free(str);  /* addfn() made a copy of the string. */
   27.28 +                SDL_AddAudioDevice(SDL_FALSE, str, (void *) ((size_t) i));
   27.29 +                SDL_free(str);  /* SDL_AddAudioDevice made a copy of the string. */
   27.30              }
   27.31          }
   27.32      }
   27.33 @@ -169,8 +166,8 @@
   27.34  static void STDMETHODCALLTYPE
   27.35  VoiceCBOnVoiceError(THIS_ void *data, HRESULT Error)
   27.36  {
   27.37 -    /* !!! FIXME: attempt to recover, or mark device disconnected. */
   27.38 -    SDL_assert(0 && "write me!");
   27.39 +    SDL_AudioDevice *this = (SDL_AudioDevice *) data;
   27.40 +    SDL_OpenedAudioDeviceDisconnected(this);
   27.41  }
   27.42  
   27.43  /* no-op callbacks... */
   27.44 @@ -221,7 +218,7 @@
   27.45  
   27.46      if (result != S_OK) {  /* uhoh, panic! */
   27.47          IXAudio2SourceVoice_FlushSourceBuffers(source);
   27.48 -        SDL_AudioDeviceDisconnected(SDL_FALSE, this);
   27.49 +        SDL_OpenedAudioDeviceDisconnected(this);
   27.50      }
   27.51  }
   27.52  
   27.53 @@ -289,7 +286,7 @@
   27.54  }
   27.55  
   27.56  static int
   27.57 -XAUDIO2_OpenDevice(_THIS, const char *devname, int iscapture)
   27.58 +XAUDIO2_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
   27.59  {
   27.60      HRESULT result = S_OK;
   27.61      WAVEFORMATEX waveformat;
   27.62 @@ -300,7 +297,7 @@
   27.63  #if defined(SDL_XAUDIO2_WIN8)
   27.64      LPCWSTR devId = NULL;
   27.65  #else
   27.66 -    UINT32 devId = 0;  /* 0 == system default device. */
   27.67 +    UINT32 devId = (UINT32) ((size_t) handle);  /* 0 == system default device. */
   27.68  #endif
   27.69  
   27.70      static IXAudio2VoiceCallbackVtbl callbacks_vtable = {
   27.71 @@ -315,9 +312,7 @@
   27.72  
   27.73      static IXAudio2VoiceCallback callbacks = { &callbacks_vtable };
   27.74  
   27.75 -    if (iscapture) {
   27.76 -        return SDL_SetError("XAudio2: capture devices unsupported.");
   27.77 -    } else if (XAudio2Create(&ixa2, 0, XAUDIO2_DEFAULT_PROCESSOR) != S_OK) {
   27.78 +    if (XAudio2Create(&ixa2, 0, XAUDIO2_DEFAULT_PROCESSOR) != S_OK) {
   27.79          return SDL_SetError("XAudio2: XAudio2Create() failed at open.");
   27.80      }
   27.81  
   27.82 @@ -332,37 +327,6 @@
   27.83      ixa2->SetDebugConfiguration(&debugConfig);
   27.84      */
   27.85  
   27.86 -#if ! defined(__WINRT__)
   27.87 -    if (devname != NULL) {
   27.88 -        UINT32 devcount = 0;
   27.89 -        UINT32 i = 0;
   27.90 -
   27.91 -        if (IXAudio2_GetDeviceCount(ixa2, &devcount) != S_OK) {
   27.92 -            IXAudio2_Release(ixa2);
   27.93 -            return SDL_SetError("XAudio2: IXAudio2_GetDeviceCount() failed.");
   27.94 -        }
   27.95 -        for (i = 0; i < devcount; i++) {
   27.96 -            XAUDIO2_DEVICE_DETAILS details;
   27.97 -            if (IXAudio2_GetDeviceDetails(ixa2, i, &details) == S_OK) {
   27.98 -                char *str = WIN_StringToUTF8(details.DisplayName);
   27.99 -                if (str != NULL) {
  27.100 -                    const int match = (SDL_strcmp(str, devname) == 0);
  27.101 -                    SDL_free(str);
  27.102 -                    if (match) {
  27.103 -                        devId = i;
  27.104 -                        break;
  27.105 -                    }
  27.106 -                }
  27.107 -            }
  27.108 -        }
  27.109 -
  27.110 -        if (i == devcount) {
  27.111 -            IXAudio2_Release(ixa2);
  27.112 -            return SDL_SetError("XAudio2: Requested device not found.");
  27.113 -        }
  27.114 -    }
  27.115 -#endif
  27.116 -
  27.117      /* Initialize all variables that we clean on shutdown */
  27.118      this->hidden = (struct SDL_PrivateAudioData *)
  27.119          SDL_malloc((sizeof *this->hidden));
  27.120 @@ -529,6 +493,16 @@
  27.121      impl->CloseDevice = XAUDIO2_CloseDevice;
  27.122      impl->Deinitialize = XAUDIO2_Deinitialize;
  27.123  
  27.124 +    /* !!! FIXME: We can apparently use a C++ interface on Windows 8
  27.125 +     * !!! FIXME: (Windows::Devices::Enumeration::DeviceInformation) for device
  27.126 +     * !!! FIXME: detection, but it's not implemented here yet.
  27.127 +     * !!! FIXME:  see http://blogs.msdn.com/b/chuckw/archive/2012/04/02/xaudio2-and-windows-8-consumer-preview.aspx
  27.128 +     * !!! FIXME:  for now, force the default device.
  27.129 +     */
  27.130 +#if defined(SDL_XAUDIO2_WIN8) || defined(__WINRT__)
  27.131 +    impl->OnlyHasDefaultOutputDevice = 1;
  27.132 +#endif
  27.133 +
  27.134      return 1;   /* this audio target is available. */
  27.135  #endif
  27.136  }