Commit 9b9b9261 authored by Matthew Gregan's avatar Matthew Gregan
Browse files

Bug 923992 - Call GetDefaultAudioEndpoint when needed rather than caching its...

Bug 923992 - Call GetDefaultAudioEndpoint when needed rather than caching its result when called at cubeb init time.  r=padenot

--HG--
extra : rebase_source : 3eaf73bf5a19e0b1997f7943bd29aa3e232c019f
parent 0f45a4d5
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -5,4 +5,4 @@ Makefile.in build files for the Mozilla build system.

The cubeb git repository is: git://github.com/kinetiknz/cubeb.git

The git commit ID used was 8c78a282aa0320e997436d6832024efe1527ca1c.
The git commit ID used was 6ba033d2a3ebd10c1d4a2b9d2032c3675c9176ce.
+79 −46
Original line number Diff line number Diff line
@@ -88,7 +88,6 @@ extern cubeb_ops const wasapi_ops;
struct cubeb
{
  cubeb_ops const * ops;
  IMMDevice * device;
  /* Library dynamically opened to increase the render
   * thread priority, and the two function pointers we need. */
  HMODULE mmcss_module;
@@ -424,47 +423,49 @@ BOOL WINAPI revert_mm_thread_characteristics_noop(HANDLE mmcss_handle)
{
  return true;
}
} // namespace anonymous

extern "C" {
int wasapi_init(cubeb ** context, char const * context_name)
HRESULT get_default_endpoint(IMMDevice ** device)
{
  HRESULT hr;
  IMMDeviceEnumerator * enumerator = NULL;

  hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
  if (FAILED(hr)) {
    LOG("Could not init COM.");
    return CUBEB_ERROR;
  }

  cubeb * ctx = (cubeb *)calloc(1, sizeof(cubeb));

  ctx->ops = &wasapi_ops;

  hr = CoCreateInstance(__uuidof(MMDeviceEnumerator),
  IMMDeviceEnumerator * enumerator;
  HRESULT hr = CoCreateInstance(__uuidof(MMDeviceEnumerator),
                                NULL, CLSCTX_INPROC_SERVER,
                                IID_PPV_ARGS(&enumerator));
  if (FAILED(hr)) {
    LOG("Could not get device enumerator.");
    wasapi_destroy(ctx);
    return CUBEB_ERROR;
    return hr;
  }

  /* eMultimedia is okay for now ("Music, movies, narration, [...]").
   * We will need to change this when we distinguish streams by use-case, other
   * possible values being eConsole ("Games, system notification sounds [...]")
   * and eCommunication ("Voice communication"). */
  hr = enumerator->GetDefaultAudioEndpoint(eRender,
                                           eMultimedia,
                                           &ctx->device);
  hr = enumerator->GetDefaultAudioEndpoint(eRender, eMultimedia, device);
  if (FAILED(hr)) {
    LOG("Could not get default audio endpoint.");
    SafeRelease(enumerator);
    wasapi_destroy(ctx);
    return hr;
  }

  SafeRelease(enumerator);

  return ERROR_SUCCESS;
}
} // namespace anonymous

extern "C" {
int wasapi_init(cubeb ** context, char const * context_name)
{
  HRESULT hr;

  hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
  if (FAILED(hr)) {
    LOG("Could not init COM.");
    return CUBEB_ERROR;
  }

  cubeb * ctx = (cubeb *)calloc(1, sizeof(cubeb));

  ctx->ops = &wasapi_ops;

  ctx->mmcss_module = LoadLibraryA("Avrt.dll");

  if (ctx->mmcss_module) {
@@ -486,8 +487,6 @@ int wasapi_init(cubeb ** context, char const * context_name)
    ctx->revert_mm_thread_characteristics = &revert_mm_thread_characteristics_noop;
  }

  SafeRelease(enumerator);

  *context = ctx;

  return CUBEB_OK;
@@ -498,7 +497,6 @@ namespace {

void wasapi_destroy(cubeb * context)
{
  SafeRelease(context->device);
  if (context->mmcss_module) {
    FreeLibrary(context->mmcss_module);
  }
@@ -513,21 +511,28 @@ char const* wasapi_get_backend_id(cubeb * context)
int
wasapi_get_max_channel_count(cubeb * ctx, uint32_t * max_channels)
{
  HRESULT hr;
  IAudioClient * client;
  WAVEFORMATEX * mix_format;

  assert(ctx && max_channels);

  hr = ctx->device->Activate(__uuidof(IAudioClient),
  IMMDevice * device;
  HRESULT hr = get_default_endpoint(&device);
  if (FAILED(hr)) {
    return CUBEB_ERROR;
  }

  hr = device->Activate(__uuidof(IAudioClient),
                        CLSCTX_INPROC_SERVER,
                        NULL, (void **)&client);
  SafeRelease(device);
  if (FAILED(hr)) {
    return CUBEB_ERROR;
  }

  hr = client->GetMixFormat(&mix_format);
  if (FAILED(hr)) {
    SafeRelease(client);
    return CUBEB_ERROR;
  }

@@ -546,16 +551,26 @@ wasapi_get_min_latency(cubeb * ctx, cubeb_stream_params params, uint32_t * laten
  IAudioClient * client;
  REFERENCE_TIME default_period;

  hr = ctx->device->Activate(__uuidof(IAudioClient),
  IMMDevice * device;
  hr = get_default_endpoint(&device);
  if (FAILED(hr)) {
    return CUBEB_ERROR;
  }

  hr = device->Activate(__uuidof(IAudioClient),
                        CLSCTX_INPROC_SERVER,
                        NULL, (void **)&client);

  SafeRelease(device);
  if (FAILED(hr)) {
    return CUBEB_ERROR;
  }

  /* The second parameter is for exclusive mode, that we don't use. */
  hr = client->GetDevicePeriod(&default_period, NULL);
  if (FAILED(hr)) {
    SafeRelease(client);
    return CUBEB_ERROR;
  }

  /* According to the docs, the best latency we can achieve is by synchronizing
   * the stream and the engine.
@@ -574,16 +589,21 @@ wasapi_get_preferred_sample_rate(cubeb * ctx, uint32_t * rate)
  IAudioClient * client;
  WAVEFORMATEX * mix_format;

  hr = ctx->device->Activate(__uuidof(IAudioClient),
  IMMDevice * device;
  hr = get_default_endpoint(&device);
  if (FAILED(hr)) {
    return CUBEB_ERROR;
  };

  hr = device->Activate(__uuidof(IAudioClient),
                        CLSCTX_INPROC_SERVER,
                        NULL, (void **)&client);

  SafeRelease(device);
  if (FAILED(hr)) {
    return CUBEB_ERROR;
  }

  hr = client->GetMixFormat(&mix_format);

  if (FAILED(hr)) {
    SafeRelease(client);
    return CUBEB_ERROR;
@@ -711,11 +731,19 @@ wasapi_stream_init(cubeb * context, cubeb_stream ** stream,
    return CUBEB_ERROR;
  }

  IMMDevice * device;
  hr = get_default_endpoint(&device);
  if (FAILED(hr)) {
    wasapi_stream_destroy(stm);
    return CUBEB_ERROR;
  }

  /* Get a client. We will get all other interfaces we need from
   * this pointer. */
  hr = context->device->Activate(__uuidof(IAudioClient),
  hr = device->Activate(__uuidof(IAudioClient),
                        CLSCTX_INPROC_SERVER,
                        NULL, (void **)&stm->client);
  SafeRelease(device);
  if (FAILED(hr)) {
    LOG("Could not activate the device to get an audio client.");
    wasapi_stream_destroy(stm);
@@ -724,7 +752,12 @@ wasapi_stream_init(cubeb * context, cubeb_stream ** stream,

  /* We have to distinguish between the format the mixer uses,
  * and the format the stream we want to play uses. */
  stm->client->GetMixFormat(&mix_format);
  hr = stm->client->GetMixFormat(&mix_format);
  if (FAILED(hr)) {
    LOG("Could not fetch current mix format from the audio client.");
    wasapi_stream_destroy(stm);
    return CUBEB_ERROR;
  }

  handle_channel_layout(stm, &mix_format, &stream_params);