Beispiel #1
0
static void thread_resume(struct ao *ao)
{
    struct wasapi_state *state = ao->priv;
    HRESULT hr;

    MP_DBG(state, "Thread Resume\n");
    UINT32 padding = 0;
    hr = IAudioClient_GetCurrentPadding(state->pAudioClient, &padding);
    if (hr != S_OK) {
        MP_ERR(state, "IAudioClient_GetCurrentPadding returned %s\n",
               mp_HRESULT_to_str(hr));
    }

    // Fill the buffer before starting, but only if there is no audio queued to
    // play.  This prevents overfilling the buffer, which leads to problems in
    // exclusive mode
    if (padding < (UINT32) state->bufferFrameCount)
        thread_feed(ao);

    // start feeding next wakeup if something else hasn't been requested
    int expected = WASAPI_THREAD_RESUME;
    atomic_compare_exchange_strong(&state->thread_state, &expected,
                                   WASAPI_THREAD_FEED);
    hr = IAudioClient_Start(state->pAudioClient);
    if (hr != S_OK) {
        MP_ERR(state, "IAudioClient_Start returned %s\n",
               mp_HRESULT_to_str(hr));
    }

    return;
}
Beispiel #2
0
static DWORD __stdcall ThreadLoop(void *lpParameter)
{
    struct ao *ao = lpParameter;
    if (!ao || !ao->priv)
        return -1;
    struct wasapi_state *state = (struct wasapi_state *)ao->priv;
    if (wasapi_thread_init(ao))
        goto exit_label;

    MSG msg;
    DWORD waitstatus = WAIT_FAILED;
    HANDLE playcontrol[] =
        {state->hUninit, state->hFeed, state->hForceFeed, NULL};
    MP_VERBOSE(ao, "Entering dispatch loop!\n");
    while (1) { /* watch events */
        waitstatus = MsgWaitForMultipleObjects(3, playcontrol, FALSE, INFINITE,
                                               QS_POSTMESSAGE | QS_SENDMESSAGE);
        switch (waitstatus) {
        case WAIT_OBJECT_0: /*shutdown*/
            wasapi_thread_uninit(state);
            goto exit_label;
        case (WAIT_OBJECT_0 + 1): /* feed */
            thread_feed(ao);
            break;
        case (WAIT_OBJECT_0 + 2): /* force feed */
            thread_feed(ao);
            SetEvent(state->hFeedDone);
            break;
        case (WAIT_OBJECT_0 + 3): /* messages to dispatch (COM marshalling) */
            while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
                DispatchMessage(&msg);
            }
            break;
        case WAIT_FAILED: /* ??? */
            return -1;
        }
    }
exit_label:
    /* dispatch any possible pending messages */
    while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
        DispatchMessage(&msg);
    }
    return state->init_ret;
}
Beispiel #3
0
static DWORD __stdcall AudioThread(void *lpParameter)
{
    struct ao *ao = lpParameter;
    struct wasapi_state *state = ao->priv;
    CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);

    state->init_ret = wasapi_thread_init(ao);
    SetEvent(state->hInitDone);
    if (state->init_ret != S_OK)
        goto exit_label;

    MP_DBG(ao, "Entering dispatch loop\n");
    while (true) { // watch events
        HANDLE events[] = {state->hWake};
        switch (MsgWaitForMultipleObjects(MP_ARRAY_SIZE(events), events,
                                          FALSE, INFINITE,
                                          QS_POSTMESSAGE | QS_SENDMESSAGE)) {
        // AudioThread wakeup
        case WAIT_OBJECT_0:
            switch (atomic_load(&state->thread_state)) {
            case WASAPI_THREAD_FEED:
                thread_feed(ao);
                break;
            case WASAPI_THREAD_RESET:
                thread_reset(ao);
                break;
            case WASAPI_THREAD_RESUME:
                thread_reset(ao);
                thread_resume(ao);
                break;
            case WASAPI_THREAD_SHUTDOWN:
                thread_reset(ao);
                goto exit_label;
            default:
                MP_ERR(ao, "Unhandled thread state\n");
                goto exit_label;
            }
            break;
        // messages to dispatch (COM marshalling)
        case (WAIT_OBJECT_0 + MP_ARRAY_SIZE(events)):
            wasapi_dispatch(ao);
            break;
        default:
            MP_ERR(ao, "Unhandled thread event\n");
            goto exit_label;
        }
    }
exit_label:
    wasapi_thread_uninit(ao);

    CoUninitialize();
    MP_DBG(ao, "Thread return\n");
    return 0;
}