Example #1
0
static void test_uninitialized(IAudioClient *ac)
{
    HRESULT hr;
    UINT32 num;
    REFERENCE_TIME t1;

    HANDLE handle = CreateEventW(NULL, FALSE, FALSE, NULL);
    IUnknown *unk;

    hr = IAudioClient_GetBufferSize(ac, &num);
    ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Uninitialized GetBufferSize call returns %08x\n", hr);

    hr = IAudioClient_GetStreamLatency(ac, &t1);
    ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Uninitialized GetStreamLatency call returns %08x\n", hr);

    hr = IAudioClient_GetCurrentPadding(ac, &num);
    ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Uninitialized GetCurrentPadding call returns %08x\n", hr);

    hr = IAudioClient_Start(ac);
    ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Uninitialized Start call returns %08x\n", hr);

    hr = IAudioClient_Stop(ac);
    ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Uninitialized Stop call returns %08x\n", hr);

    hr = IAudioClient_Reset(ac);
    ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Uninitialized Reset call returns %08x\n", hr);

    hr = IAudioClient_SetEventHandle(ac, handle);
    ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Uninitialized SetEventHandle call returns %08x\n", hr);

    hr = IAudioClient_GetService(ac, &IID_IAudioStreamVolume, (void**)&unk);
    ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Uninitialized GetService call returns %08x\n", hr);

    CloseHandle(handle);
}
JNIEXPORT void JNICALL
Java_org_jitsi_impl_neomedia_jmfext_media_protocol_wasapi_WASAPI_IAudioClient_1SetEventHandle
    (JNIEnv *env, jclass clazz, jlong thiz, jlong eventHandle)
{
    HRESULT hr
        = IAudioClient_SetEventHandle(
                (IAudioClient *) (intptr_t) thiz,
                (HANDLE) (intptr_t) eventHandle);

    if (FAILED(hr))
        WASAPI_throwNewHResultException(env, hr, __func__, __LINE__);
}
Example #3
0
static gboolean
gst_wasapi_sink_start (GstBaseSink * sink)
{
  GstWasapiSink *self = GST_WASAPI_SINK (sink);
  gboolean res = FALSE;
  IAudioClient *client = NULL;
  HRESULT hr;
  IAudioRenderClient *render_client = NULL;

  if (!gst_wasapi_util_get_default_device_client (GST_ELEMENT (self),
          FALSE, self->rate, self->buffer_time, self->period_time,
          AUDCLNT_STREAMFLAGS_EVENTCALLBACK, &client, &self->latency))
    goto beach;

  hr = IAudioClient_SetEventHandle (client, self->event_handle);
  if (hr != S_OK) {
    GST_ERROR_OBJECT (self, "IAudioClient::SetEventHandle () failed");
    goto beach;
  }

  hr = IAudioClient_GetService (client, &IID_IAudioRenderClient,
      &render_client);
  if (hr != S_OK) {
    GST_ERROR_OBJECT (self, "IAudioClient::GetService "
        "(IID_IAudioRenderClient) failed");
    goto beach;
  }

  hr = IAudioClient_Start (client);
  if (hr != S_OK) {
    GST_ERROR_OBJECT (self, "IAudioClient::Start failed");
    goto beach;
  }

  self->client = client;
  self->render_client = render_client;

  res = TRUE;

beach:
  if (!res) {
    if (render_client != NULL)
      IUnknown_Release (render_client);

    if (client != NULL)
      IUnknown_Release (client);
  }

  return res;
}
Example #4
0
static void test_event(void)
{
    HANDLE event;
    HRESULT hr;
    IAudioClient *ac;
    WAVEFORMATEX *pwfx;

    hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
            NULL, (void**)&ac);
    ok(hr == S_OK, "Activation failed with %08x\n", hr);
    if(hr != S_OK)
        return;

    hr = IAudioClient_GetMixFormat(ac, &pwfx);
    ok(hr == S_OK, "GetMixFormat failed: %08x\n", hr);
    if(hr != S_OK)
        return;

    hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED,
            AUDCLNT_STREAMFLAGS_EVENTCALLBACK, 5000000,
            0, pwfx, NULL);
    ok(hr == S_OK, "Initialize failed: %08x\n", hr);

    CoTaskMemFree(pwfx);

    event = CreateEventW(NULL, FALSE, FALSE, NULL);
    ok(event != NULL, "CreateEvent failed\n");

    hr = IAudioClient_Start(ac);
    ok(hr == AUDCLNT_E_EVENTHANDLE_NOT_SET, "Start failed: %08x\n", hr);

    hr = IAudioClient_SetEventHandle(ac, event);
    ok(hr == S_OK, "SetEventHandle failed: %08x\n", hr);

    hr = IAudioClient_Start(ac);
    ok(hr == S_OK, "Start failed: %08x\n", hr);

    hr = IAudioClient_Stop(ac);
    ok(hr == S_OK, "Start failed: %08x\n", hr);

    /* test releasing a playing stream */
    hr = IAudioClient_Start(ac);
    ok(hr == S_OK, "Start failed: %08x\n", hr);
    IAudioClient_Release(ac);

    CloseHandle(event);
}
Example #5
0
static void test_audioclient(void)
{
    IAudioClient *ac;
    IUnknown *unk;
    HRESULT hr;
    ULONG ref;
    WAVEFORMATEX *pwfx, *pwfx2;
    REFERENCE_TIME t1, t2;
    HANDLE handle;

    hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
            NULL, (void**)&ac);
    ok(hr == S_OK, "Activation failed with %08x\n", hr);
    if(hr != S_OK)
        return;

    handle = CreateEventW(NULL, FALSE, FALSE, NULL);

    hr = IAudioClient_QueryInterface(ac, &IID_IUnknown, NULL);
    ok(hr == E_POINTER, "QueryInterface(NULL) returned %08x\n", hr);

    unk = (void*)(LONG_PTR)0x12345678;
    hr = IAudioClient_QueryInterface(ac, &IID_NULL, (void**)&unk);
    ok(hr == E_NOINTERFACE, "QueryInterface(IID_NULL) returned %08x\n", hr);
    ok(!unk, "QueryInterface(IID_NULL) returned non-null pointer %p\n", unk);

    hr = IAudioClient_QueryInterface(ac, &IID_IUnknown, (void**)&unk);
    ok(hr == S_OK, "QueryInterface(IID_IUnknown) returned %08x\n", hr);
    if (unk)
    {
        ref = IUnknown_Release(unk);
        ok(ref == 1, "Released count is %u\n", ref);
    }

    hr = IAudioClient_QueryInterface(ac, &IID_IAudioClient, (void**)&unk);
    ok(hr == S_OK, "QueryInterface(IID_IAudioClient) returned %08x\n", hr);
    if (unk)
    {
        ref = IUnknown_Release(unk);
        ok(ref == 1, "Released count is %u\n", ref);
    }

    hr = IAudioClient_GetDevicePeriod(ac, NULL, NULL);
    ok(hr == E_POINTER, "Invalid GetDevicePeriod call returns %08x\n", hr);

    hr = IAudioClient_GetDevicePeriod(ac, &t1, NULL);
    ok(hr == S_OK, "Valid GetDevicePeriod call returns %08x\n", hr);

    hr = IAudioClient_GetDevicePeriod(ac, NULL, &t2);
    ok(hr == S_OK, "Valid GetDevicePeriod call returns %08x\n", hr);

    hr = IAudioClient_GetDevicePeriod(ac, &t1, &t2);
    ok(hr == S_OK, "Valid GetDevicePeriod call returns %08x\n", hr);
    trace("Returned periods: %u.%05u ms %u.%05u ms\n",
          (UINT)(t1/10000), (UINT)(t1 % 10000),
          (UINT)(t2/10000), (UINT)(t2 % 10000));

    hr = IAudioClient_GetMixFormat(ac, NULL);
    ok(hr == E_POINTER, "GetMixFormat returns %08x\n", hr);

    hr = IAudioClient_GetMixFormat(ac, &pwfx);
    ok(hr == S_OK, "Valid GetMixFormat returns %08x\n", hr);

    if (hr == S_OK)
    {
        trace("pwfx: %p\n", pwfx);
        trace("Tag: %04x\n", pwfx->wFormatTag);
        trace("bits: %u\n", pwfx->wBitsPerSample);
        trace("chan: %u\n", pwfx->nChannels);
        trace("rate: %u\n", pwfx->nSamplesPerSec);
        trace("align: %u\n", pwfx->nBlockAlign);
        trace("extra: %u\n", pwfx->cbSize);
        ok(pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE, "wFormatTag is %x\n", pwfx->wFormatTag);
        if (pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE)
        {
            WAVEFORMATEXTENSIBLE *pwfxe = (void*)pwfx;
            trace("Res: %u\n", pwfxe->Samples.wReserved);
            trace("Mask: %x\n", pwfxe->dwChannelMask);
            trace("Alg: %s\n",
                  IsEqualGUID(&pwfxe->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM)?"PCM":
                  (IsEqualGUID(&pwfxe->SubFormat,
                               &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)?"FLOAT":"Other"));
        }

        hr = IAudioClient_IsFormatSupported(ac, AUDCLNT_SHAREMODE_SHARED, pwfx, &pwfx2);
        ok(hr == S_OK, "Valid IsFormatSupported(Shared) call returns %08x\n", hr);
        ok(pwfx2 == NULL, "pwfx2 is non-null\n");
        CoTaskMemFree(pwfx2);

        hr = IAudioClient_IsFormatSupported(ac, AUDCLNT_SHAREMODE_SHARED, NULL, NULL);
        ok(hr == E_POINTER, "IsFormatSupported(NULL) call returns %08x\n", hr);

        hr = IAudioClient_IsFormatSupported(ac, AUDCLNT_SHAREMODE_SHARED, pwfx, NULL);
        ok(hr == E_POINTER, "IsFormatSupported(Shared,NULL) call returns %08x\n", hr);

        hr = IAudioClient_IsFormatSupported(ac, AUDCLNT_SHAREMODE_EXCLUSIVE, pwfx, NULL);
        ok(hr == S_OK || hr == AUDCLNT_E_UNSUPPORTED_FORMAT, "IsFormatSupported(Exclusive) call returns %08x\n", hr);

        hr = IAudioClient_IsFormatSupported(ac, AUDCLNT_SHAREMODE_EXCLUSIVE, pwfx, &pwfx2);
        ok(hr == S_OK || hr == AUDCLNT_E_UNSUPPORTED_FORMAT, "IsFormatSupported(Exclusive) call returns %08x\n", hr);
        ok(pwfx2 == NULL, "pwfx2 non-null on exclusive IsFormatSupported\n");

        hr = IAudioClient_IsFormatSupported(ac, 0xffffffff, pwfx, NULL);
        ok(hr == E_INVALIDARG ||
           hr == AUDCLNT_E_UNSUPPORTED_FORMAT,
           "IsFormatSupported(0xffffffff) call returns %08x\n", hr);
    }

    test_uninitialized(ac);

    hr = IAudioClient_Initialize(ac, 3, 0, 5000000, 0, pwfx, NULL);
    ok(hr == AUDCLNT_E_NOT_INITIALIZED, "Initialize with invalid sharemode returns %08x\n", hr);

    hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0xffffffff, 5000000, 0, pwfx, NULL);
    ok(hr == E_INVALIDARG, "Initialize with invalid flags returns %08x\n", hr);

    /* It seems that if length > 2s or periodicity != 0 the length is ignored and call succeeds
     * Since we can only initialize successfully once, skip those tests.
     */
    hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 5000000, 0, NULL, NULL);
    ok(hr == E_POINTER, "Initialize with null format returns %08x\n", hr);

    hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 5000000, 0, pwfx, NULL);
    ok(hr == S_OK, "Valid Initialize returns %08x\n", hr);

    if (hr != S_OK)
    {
        skip("Cannot initialize %08x, remainder of tests is useless\n", hr);
        CoTaskMemFree(pwfx);
        return;
    }

    hr = IAudioClient_GetStreamLatency(ac, NULL);
    ok(hr == E_POINTER, "GetStreamLatency(NULL) call returns %08x\n", hr);

    hr = IAudioClient_GetStreamLatency(ac, &t1);
    ok(hr == S_OK, "Valid GetStreamLatency call returns %08x\n", hr);
    trace("Returned latency: %u.%05u ms\n",
          (UINT)(t1/10000), (UINT)(t1 % 10000));

    hr = IAudioClient_Initialize(ac, AUDCLNT_SHAREMODE_SHARED, 0, 5000000, 0, pwfx, NULL);
    ok(hr == AUDCLNT_E_ALREADY_INITIALIZED, "Calling Initialize twice returns %08x\n", hr);

    hr = IAudioClient_SetEventHandle(ac, NULL);
    ok(hr == E_INVALIDARG, "SetEventHandle(NULL) returns %08x\n", hr);

    hr = IAudioClient_SetEventHandle(ac, handle);
    ok(hr == AUDCLNT_E_EVENTHANDLE_NOT_EXPECTED ||
       broken(hr == HRESULT_FROM_WIN32(ERROR_INVALID_NAME)) ||
       broken(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) /* Some 2k8 */ ||
       broken(hr == HRESULT_FROM_WIN32(ERROR_BAD_PATHNAME)) /* Some Vista */
       , "SetEventHandle returns %08x\n", hr);

    hr = IAudioClient_Reset(ac);
    ok(hr == S_OK, "Reset on a resetted stream returns %08x\n", hr);

    hr = IAudioClient_Stop(ac);
    ok(hr == S_FALSE, "Stop on a stopped stream returns %08x\n", hr);

    hr = IAudioClient_Start(ac);
    ok(hr == S_OK, "Start on a stopped stream returns %08x\n", hr);

    IAudioClient_Release(ac);

    CloseHandle(handle);
    CoTaskMemFree(pwfx);
}
Example #6
0
HRESULT DSOUND_ReopenDevice(DirectSoundDevice *device, BOOL forcewave)
{
    HRESULT hres;
    REFERENCE_TIME period;
    UINT32 frames;
    DWORD period_ms;
    IAudioClient *client = NULL;
    IAudioRenderClient *render = NULL;
    IAudioStreamVolume *volume = NULL;
    DWORD fraglen;
    WAVEFORMATEX *wfx = NULL;
    DWORD oldspeakerconfig = device->speaker_config;

    TRACE("(%p, %d)\n", device, forcewave);

    hres = IMMDevice_Activate(device->mmdevice, &IID_IAudioClient,
            CLSCTX_INPROC_SERVER, NULL, (void **)&client);
    if(FAILED(hres)){
        WARN("Activate failed: %08x\n", hres);
        return hres;
    }

    hres = DSOUND_WaveFormat(device, client, forcewave, &wfx);
    if (FAILED(hres)) {
        IAudioClient_Release(client);
        return hres;
    }

    hres = IAudioClient_Initialize(client,
            AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_NOPERSIST |
            AUDCLNT_STREAMFLAGS_EVENTCALLBACK, 800000, 0, wfx, NULL);
    if(FAILED(hres)){
        IAudioClient_Release(client);
        ERR("Initialize failed: %08x\n", hres);
        return hres;
    }

    IAudioClient_SetEventHandle(client, device->sleepev);

    hres = IAudioClient_GetService(client, &IID_IAudioRenderClient, (void**)&render);
    if(FAILED(hres))
        goto err_service;

    hres = IAudioClient_GetService(client, &IID_IAudioStreamVolume, (void**)&volume);
    if(FAILED(hres))
        goto err_service;

    /* Now kick off the timer so the event fires periodically */
    hres = IAudioClient_Start(client);
    if (FAILED(hres)) {
        WARN("Start failed with %08x\n", hres);
        goto err;
    }
    hres = IAudioClient_GetStreamLatency(client, &period);
    if (FAILED(hres)) {
        WARN("GetStreamLatency failed with %08x\n", hres);
        goto err;
    }
    hres = IAudioClient_GetBufferSize(client, &frames);
    if (FAILED(hres)) {
        WARN("GetBufferSize failed with %08x\n", hres);
        goto err;
    }

    period_ms = (period + 9999) / 10000;
    fraglen = MulDiv(wfx->nSamplesPerSec, period, 10000000) * wfx->nBlockAlign;
    TRACE("period %u ms fraglen %u buflen %u\n", period_ms, fraglen, frames * wfx->nBlockAlign);

    hres = DSOUND_PrimaryOpen(device, wfx, frames, forcewave);
    if(FAILED(hres))
        goto err;

    DSOUND_ReleaseDevice(device);
    device->client = client;
    device->render = render;
    device->volume = volume;
    device->fraglen = fraglen;
    device->aclen = frames * wfx->nBlockAlign;

    if (period_ms < 3)
        device->sleeptime = 5;
    else
        device->sleeptime = period_ms * 5 / 2;

    return S_OK;

err_service:
    WARN("GetService failed: %08x\n", hres);
err:
    device->speaker_config = oldspeakerconfig;
    DSOUND_ParseSpeakerConfig(device);
    if (volume)
        IAudioStreamVolume_Release(volume);
    if (render)
        IAudioRenderClient_Release(render);
    IAudioClient_Release(client);
    HeapFree(GetProcessHeap(), 0, wfx);
    return hres;
}
static gboolean
gst_wasapi_sink_prepare (GstAudioSink * asink, GstAudioRingBufferSpec * spec)
{
  GstWasapiSink *self = GST_WASAPI_SINK (asink);
  gboolean res = FALSE;
  HRESULT hr;
  REFERENCE_TIME latency_rt, def_period, min_period;
  WAVEFORMATEXTENSIBLE format;
  IAudioRenderClient *render_client = NULL;

  hr = IAudioClient_GetDevicePeriod (self->client, &def_period, &min_period);
  if (hr != S_OK) {
    GST_ERROR_OBJECT (self, "IAudioClient::GetDevicePeriod () failed");
    goto beach;
  }

  gst_wasapi_util_audio_info_to_waveformatex (&spec->info, &format);
  self->info = spec->info;

  hr = IAudioClient_Initialize (self->client, AUDCLNT_SHAREMODE_SHARED,
      AUDCLNT_STREAMFLAGS_EVENTCALLBACK,
      spec->buffer_time / 100, 0, (WAVEFORMATEX *) & format, NULL);
  if (hr != S_OK) {
    GST_ELEMENT_ERROR (self, RESOURCE, OPEN_READ, (NULL),
        ("IAudioClient::Initialize () failed: %s",
            gst_wasapi_util_hresult_to_string (hr)));
    goto beach;
  }

  hr = IAudioClient_GetStreamLatency (self->client, &latency_rt);
  if (hr != S_OK) {
    GST_ERROR_OBJECT (self, "IAudioClient::GetStreamLatency () failed");
    goto beach;
  }

  GST_INFO_OBJECT (self, "default period: %d (%d ms), "
      "minimum period: %d (%d ms), "
      "latency: %d (%d ms)",
      (guint32) def_period, (guint32) def_period / 10000,
      (guint32) min_period, (guint32) min_period / 10000,
      (guint32) latency_rt, (guint32) latency_rt / 10000);

  /* FIXME: What to do with the latency? */

  hr = IAudioClient_SetEventHandle (self->client, self->event_handle);
  if (hr != S_OK) {
    GST_ERROR_OBJECT (self, "IAudioClient::SetEventHandle () failed");
    goto beach;
  }

  if (!gst_wasapi_util_get_render_client (GST_ELEMENT (self), self->client,
          &render_client)) {
    goto beach;
  }

  hr = IAudioClient_Start (self->client);
  if (hr != S_OK) {
    GST_ERROR_OBJECT (self, "IAudioClient::Start failed");
    goto beach;
  }

  self->render_client = render_client;
  render_client = NULL;

  res = TRUE;

beach:
  if (render_client != NULL)
    IUnknown_Release (render_client);

  return res;
}
Example #8
0
static HRESULT IDirectSoundCaptureBufferImpl_Create(
    DirectSoundCaptureDevice *device,
    IDirectSoundCaptureBufferImpl ** ppobj,
    LPCDSCBUFFERDESC lpcDSCBufferDesc)
{
    LPWAVEFORMATEX  wfex;
    IDirectSoundCaptureBufferImpl *This;
    TRACE( "(%p,%p,%p)\n", device, ppobj, lpcDSCBufferDesc);

    if (ppobj == NULL) {
	WARN("invalid parameter: ppobj == NULL\n");
	return DSERR_INVALIDPARAM;
    }

    *ppobj = NULL;

    if (!device) {
	WARN("not initialized\n");
	return DSERR_UNINITIALIZED;
    }

    if (lpcDSCBufferDesc == NULL) {
	WARN("invalid parameter: lpcDSCBufferDesc == NULL\n");
	return DSERR_INVALIDPARAM;
    }

    if ( ((lpcDSCBufferDesc->dwSize != sizeof(DSCBUFFERDESC)) &&
          (lpcDSCBufferDesc->dwSize != sizeof(DSCBUFFERDESC1))) ||
        (lpcDSCBufferDesc->dwBufferBytes == 0) ||
        (lpcDSCBufferDesc->lpwfxFormat == NULL) ) { /* FIXME: DSERR_BADFORMAT ? */
	WARN("invalid lpcDSCBufferDesc\n");
	return DSERR_INVALIDPARAM;
    }

    wfex = lpcDSCBufferDesc->lpwfxFormat;

    TRACE("(formattag=0x%04x,chans=%d,samplerate=%d,"
        "bytespersec=%d,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
        wfex->wFormatTag, wfex->nChannels, wfex->nSamplesPerSec,
        wfex->nAvgBytesPerSec, wfex->nBlockAlign,
        wfex->wBitsPerSample, wfex->cbSize);

    device->pwfx = DSOUND_CopyFormat(wfex);
    if ( device->pwfx == NULL )
	return DSERR_OUTOFMEMORY;

    This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
        sizeof(IDirectSoundCaptureBufferImpl));

    if ( This == NULL ) {
	WARN("out of memory\n");
	return DSERR_OUTOFMEMORY;
    } else {
        HRESULT err = DS_OK;
        LPBYTE newbuf;
        DWORD buflen;

        This->numIfaces = 0;
        This->ref = 0;
        This->refn = 0;
        This->device = device;
        This->device->capture_buffer = This;
        This->nrofnotifies = 0;

        This->pdscbd = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
            lpcDSCBufferDesc->dwSize);
        if (This->pdscbd)
            CopyMemory(This->pdscbd, lpcDSCBufferDesc, lpcDSCBufferDesc->dwSize);
        else {
            WARN("no memory\n");
            This->device->capture_buffer = 0;
            HeapFree( GetProcessHeap(), 0, This );
            return DSERR_OUTOFMEMORY;
        }

        This->IDirectSoundCaptureBuffer8_iface.lpVtbl = &dscbvt;
        This->IDirectSoundNotify_iface.lpVtbl = &dscnvt;

        err = IMMDevice_Activate(device->mmdevice, &IID_IAudioClient,
                CLSCTX_INPROC_SERVER, NULL, (void**)&device->client);
        if(FAILED(err)){
            WARN("Activate failed: %08x\n", err);
            HeapFree(GetProcessHeap(), 0, This->pdscbd);
            This->device->capture_buffer = 0;
            HeapFree( GetProcessHeap(), 0, This );
            return err;
        }

        err = IAudioClient_Initialize(device->client,
                AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_NOPERSIST | AUDCLNT_STREAMFLAGS_EVENTCALLBACK,
                200 * 100000, 0, device->pwfx, NULL);
        if(FAILED(err)){
            WARN("Initialize failed: %08x\n", err);
            IAudioClient_Release(device->client);
            device->client = NULL;
            HeapFree(GetProcessHeap(), 0, This->pdscbd);
            This->device->capture_buffer = 0;
            HeapFree( GetProcessHeap(), 0, This );
            if(err == AUDCLNT_E_UNSUPPORTED_FORMAT)
                return DSERR_BADFORMAT;
            return err;
        }

        This->sleepev = CreateEventW(NULL, 0, 0, NULL);

        err = IAudioClient_SetEventHandle(device->client, This->sleepev);
        if(FAILED(err)){
            WARN("SetEventHandle failed: %08x\n", err);
            IAudioClient_Release(device->client);
            device->client = NULL;
            CloseHandle(This->sleepev);
            HeapFree(GetProcessHeap(), 0, This->pdscbd);
            This->device->capture_buffer = 0;
            HeapFree( GetProcessHeap(), 0, This );
            return err;
        }

        err = IAudioClient_GetService(device->client, &IID_IAudioCaptureClient,
                (void**)&device->capture);
        if(FAILED(err)){
            WARN("GetService failed: %08x\n", err);
            IAudioClient_Release(device->client);
            device->client = NULL;
            CloseHandle(This->sleepev);
            HeapFree(GetProcessHeap(), 0, This->pdscbd);
            This->device->capture_buffer = 0;
            HeapFree( GetProcessHeap(), 0, This );
            return err;
        }

        buflen = lpcDSCBufferDesc->dwBufferBytes;
        TRACE("desired buflen=%d, old buffer=%p\n", buflen, device->buffer);
        if (device->buffer)
            newbuf = HeapReAlloc(GetProcessHeap(),0,device->buffer,buflen);
        else
            newbuf = HeapAlloc(GetProcessHeap(),0,buflen);
        if (newbuf == NULL) {
            IAudioClient_Release(device->client);
            device->client = NULL;
            IAudioCaptureClient_Release(device->capture);
            device->capture = NULL;
            CloseHandle(This->sleepev);
            HeapFree(GetProcessHeap(), 0, This->pdscbd);
            This->device->capture_buffer = 0;
            HeapFree( GetProcessHeap(), 0, This );
            return DSERR_OUTOFMEMORY;
        }
        device->buffer = newbuf;
        device->buflen = buflen;
        This->thread = CreateThread(NULL, 0, DSOUND_capture_thread, This, 0, NULL);
    }

    IDirectSoundCaptureBuffer_AddRef(&This->IDirectSoundCaptureBuffer8_iface);
    *ppobj = This;

    TRACE("returning DS_OK\n");
    return DS_OK;
}
Example #9
0
HRESULT DSOUND_ReopenDevice(DirectSoundDevice *device, BOOL forcewave)
{
    UINT prebuf_frames;
    REFERENCE_TIME prebuf_rt;
    WAVEFORMATEX *wfx = NULL;
    HRESULT hres;
    REFERENCE_TIME period;
    DWORD period_ms;

    TRACE("(%p, %d)\n", device, forcewave);

    if(device->client){
        IAudioClient_Release(device->client);
        device->client = NULL;
    }
    if(device->render){
        IAudioRenderClient_Release(device->render);
        device->render = NULL;
    }
    if(device->clock){
        IAudioClock_Release(device->clock);
        device->clock = NULL;
    }
    if(device->volume){
        IAudioStreamVolume_Release(device->volume);
        device->volume = NULL;
    }

    hres = IMMDevice_Activate(device->mmdevice, &IID_IAudioClient,
            CLSCTX_INPROC_SERVER, NULL, (void **)&device->client);
    if(FAILED(hres)) {
        WARN("Activate failed: %08x\n", hres);
        return hres;
    }

    hres = DSOUND_WaveFormat(device, device->client, forcewave, &wfx);
    if (FAILED(hres)) {
        IAudioClient_Release(device->client);
        device->client = NULL;
        return hres;
    }
    HeapFree(GetProcessHeap(), 0, device->pwfx);
    device->pwfx = wfx;

    prebuf_frames = device->prebuf * DSOUND_fraglen(device) / device->pwfx->nBlockAlign;
    prebuf_rt = (10000000 * (UINT64)prebuf_frames) / device->pwfx->nSamplesPerSec;

    hres = IAudioClient_Initialize(device->client,
            AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_NOPERSIST |
            AUDCLNT_STREAMFLAGS_EVENTCALLBACK, prebuf_rt, 0, device->pwfx, NULL);
    if(FAILED(hres)){
        IAudioClient_Release(device->client);
        device->client = NULL;
        WARN("Initialize failed: %08x\n", hres);
        return hres;
    }
    IAudioClient_SetEventHandle(device->client, device->sleepev);

    hres = IAudioClient_GetService(device->client, &IID_IAudioRenderClient,
            (void**)&device->render);
    if(FAILED(hres)){
        IAudioClient_Release(device->client);
        device->client = NULL;
        WARN("GetService failed: %08x\n", hres);
        return hres;
    }

    hres = IAudioClient_GetService(device->client, &IID_IAudioClock,
            (void**)&device->clock);
    if(FAILED(hres)){
        IAudioClient_Release(device->client);
        IAudioRenderClient_Release(device->render);
        device->client = NULL;
        device->render = NULL;
        WARN("GetService failed: %08x\n", hres);
        return hres;
    }

    hres = IAudioClient_GetService(device->client, &IID_IAudioStreamVolume,
            (void**)&device->volume);
    if(FAILED(hres)){
        IAudioClient_Release(device->client);
        IAudioRenderClient_Release(device->render);
        IAudioClock_Release(device->clock);
        device->client = NULL;
        device->render = NULL;
        device->clock = NULL;
        WARN("GetService failed: %08x\n", hres);
        return hres;
    }

    /* Now kick off the timer so the event fires periodically */
    hres = IAudioClient_Start(device->client);
    if (FAILED(hres))
        WARN("starting failed with %08x\n", hres);

    hres = IAudioClient_GetStreamLatency(device->client, &period);
    if (FAILED(hres)) {
        WARN("GetStreamLatency failed with %08x\n", hres);
        period_ms = 10;
    } else
        period_ms = (period + 9999) / 10000;
    TRACE("period %u ms fraglen %u prebuf %u\n", period_ms, device->fraglen, device->prebuf);

    if (period_ms < 3)
        device->sleeptime = 5;
    else
        device->sleeptime = period_ms * 5 / 2;

    return S_OK;
}
Example #10
0
static DWORD CALLBACK MMDevApiMsgProc(void *ptr)
{
    ThreadRequest *req = ptr;
    IMMDeviceEnumerator *Enumerator;
    ALuint deviceCount = 0;
    MMDevApiData *data;
    ALCdevice *device;
    HRESULT hr, cohr;
    MSG msg;

    TRACE("Starting message thread\n");

    cohr = CoInitialize(NULL);
    if(FAILED(cohr))
    {
        WARN("Failed to initialize COM: 0x%08lx\n", cohr);
        req->result = cohr;
        SetEvent(req->FinishedEvt);
        return 0;
    }

    hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, &ptr);
    if(FAILED(hr))
    {
        WARN("Failed to create IMMDeviceEnumerator instance: 0x%08lx\n", hr);
        CoUninitialize();
        req->result = hr;
        SetEvent(req->FinishedEvt);
        return 0;
    }
    Enumerator = ptr;
    IMMDeviceEnumerator_Release(Enumerator);
    Enumerator = NULL;

    CoUninitialize();

    req->result = S_OK;
    SetEvent(req->FinishedEvt);

    TRACE("Starting message loop\n");
    while(GetMessage(&msg, NULL, 0, 0))
    {
        TRACE("Got message %u\n", msg.message);
        switch(msg.message)
        {
        case WM_USER_OpenDevice:
            req = (ThreadRequest*)msg.wParam;
            device = (ALCdevice*)msg.lParam;
            data = device->ExtraData;

            hr = cohr = S_OK;
            if(++deviceCount == 1)
                hr = cohr = CoInitialize(NULL);
            if(SUCCEEDED(hr))
                hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, &ptr);
            if(SUCCEEDED(hr))
            {
                Enumerator = ptr;
                if(!data->devid)
                    hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(Enumerator, eRender, eMultimedia, &data->mmdev);
                else
                    hr = IMMDeviceEnumerator_GetDevice(Enumerator, data->devid, &data->mmdev);
                IMMDeviceEnumerator_Release(Enumerator);
                Enumerator = NULL;
            }
            if(SUCCEEDED(hr))
                hr = IMMDevice_Activate(data->mmdev, &IID_IAudioClient, CLSCTX_INPROC_SERVER, NULL, &ptr);
            if(SUCCEEDED(hr))
            {
                data->client = ptr;
                device->DeviceName = get_device_name(data->mmdev);
            }

            if(FAILED(hr))
            {
                if(data->mmdev)
                    IMMDevice_Release(data->mmdev);
                data->mmdev = NULL;
                if(--deviceCount == 0 && SUCCEEDED(cohr))
                    CoUninitialize();
            }

            req->result = hr;
            SetEvent(req->FinishedEvt);
            continue;

        case WM_USER_ResetDevice:
            req = (ThreadRequest*)msg.wParam;
            device = (ALCdevice*)msg.lParam;

            req->result = DoReset(device);
            SetEvent(req->FinishedEvt);
            continue;

        case WM_USER_StartDevice:
            req = (ThreadRequest*)msg.wParam;
            device = (ALCdevice*)msg.lParam;
            data = device->ExtraData;

            ResetEvent(data->NotifyEvent);
            hr = IAudioClient_SetEventHandle(data->client, data->NotifyEvent);
            if(FAILED(hr))
                ERR("Failed to set event handle: 0x%08lx\n", hr);
            else
            {
                hr = IAudioClient_Start(data->client);
                if(FAILED(hr))
                    ERR("Failed to start audio client: 0x%08lx\n", hr);
            }

            if(SUCCEEDED(hr))
                hr = IAudioClient_GetService(data->client, &IID_IAudioRenderClient, &ptr);
            if(SUCCEEDED(hr))
            {
                data->render = ptr;
                data->thread = StartThread(MMDevApiProc, device);
                if(!data->thread)
                {
                    if(data->render)
                        IAudioRenderClient_Release(data->render);
                    data->render = NULL;
                    IAudioClient_Stop(data->client);
                    ERR("Failed to start thread\n");
                    hr = E_FAIL;
                }
            }

            req->result = hr;
            SetEvent(req->FinishedEvt);
            continue;

        case WM_USER_StopDevice:
            req = (ThreadRequest*)msg.wParam;
            device = (ALCdevice*)msg.lParam;
            data = device->ExtraData;

            if(data->thread)
            {
                data->killNow = 1;
                StopThread(data->thread);
                data->thread = NULL;

                data->killNow = 0;

                IAudioRenderClient_Release(data->render);
                data->render = NULL;
                IAudioClient_Stop(data->client);
            }

            req->result = S_OK;
            SetEvent(req->FinishedEvt);
            continue;

        case WM_USER_CloseDevice:
            req = (ThreadRequest*)msg.wParam;
            device = (ALCdevice*)msg.lParam;
            data = device->ExtraData;

            IAudioClient_Release(data->client);
            data->client = NULL;

            IMMDevice_Release(data->mmdev);
            data->mmdev = NULL;

            if(--deviceCount == 0)
                CoUninitialize();

            req->result = S_OK;
            SetEvent(req->FinishedEvt);
            continue;

        case WM_USER_Enumerate:
            req = (ThreadRequest*)msg.wParam;

            hr = cohr = S_OK;
            if(++deviceCount == 1)
                hr = cohr = CoInitialize(NULL);
            if(SUCCEEDED(hr))
                hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, &ptr);
            if(SUCCEEDED(hr))
            {
                EDataFlow flowdir;
                DevMap **devlist;
                ALuint *numdevs;
                ALuint i;

                Enumerator = ptr;
                if(msg.lParam == CAPTURE_DEVICE_PROBE)
                {
                    flowdir = eCapture;
                    devlist = &CaptureDeviceList;
                    numdevs = &NumCaptureDevices;
                }
                else
                {
                    flowdir = eRender;
                    devlist = &PlaybackDeviceList;
                    numdevs = &NumPlaybackDevices;
                }

                for(i = 0;i < *numdevs;i++)
                {
                    free((*devlist)[i].name);
                    free((*devlist)[i].devid);
                }
                free(*devlist);
                *devlist = NULL;
                *numdevs = 0;

                *devlist = ProbeDevices(Enumerator, flowdir, numdevs);

                IMMDeviceEnumerator_Release(Enumerator);
                Enumerator = NULL;
            }

            if(--deviceCount == 0 && SUCCEEDED(cohr))
                CoUninitialize();

            req->result = S_OK;
            SetEvent(req->FinishedEvt);
            continue;

        default:
            ERR("Unexpected message: %u\n", msg.message);
            continue;
        }
    }
    TRACE("Message loop finished\n");

    return 0;
}