Exemplo n.º 1
0
static HRESULT STDMETHODCALLTYPE sIMMNotificationClient_OnDeviceStateChanged(
    IMMNotificationClient *This,
    LPCWSTR pwstrDeviceId,
    DWORD dwNewState)
{
    change_notify *change = (change_notify *)This;
    struct ao *ao = change->ao;

    if (change->is_hotplug) {
        MP_VERBOSE(ao,
                   "OnDeviceStateChanged triggered: sending hotplug event\n");
        ao_hotplug_event(ao);
    } else if (pwstrDeviceId && !wcscmp(pwstrDeviceId, change->monitored)) {
        switch (dwNewState) {
        case DEVICE_STATE_DISABLED:
        case DEVICE_STATE_NOTPRESENT:
        case DEVICE_STATE_UNPLUGGED:
            MP_VERBOSE(ao, "OnDeviceStateChanged triggered on device %S: "
                       "requesting ao reload\n", pwstrDeviceId);
            ao_request_reload(ao);
            break;
        case DEVICE_STATE_ACTIVE:
            break;
        }
    }

    return S_OK;
}
Exemplo n.º 2
0
static HRESULT STDMETHODCALLTYPE sIMMNotificationClient_OnDefaultDeviceChanged(
    IMMNotificationClient *This,
    EDataFlow flow,
    ERole role,
    LPCWSTR pwstrDeviceId)
{
    change_notify *change = (change_notify *)This;
    struct ao *ao = change->ao;
    struct wasapi_state *state = (struct wasapi_state *)ao->priv;

    MP_VERBOSE(ao, "OnDefaultDeviceChanged triggered for role:%s flow:%s\n",
               ERole_to_str(role), EDataFlow_to_str(flow));
    if(pwstrDeviceId)
        MP_VERBOSE(ao, "New default device %S\n", pwstrDeviceId);

    /* don't care about "eCapture" or non-"eMultimedia" roles  */
    if (flow == eCapture || role != eMultimedia) return S_OK;

    /* stay on the device the user specified */
    if (state->opt_device) {
        MP_VERBOSE(ao, "Staying on specified device \"%s\"", state->opt_device);
        return S_OK;
    }

    /* don't reload if already on the new default */
    if (pwstrDeviceId && !wcscmp(change->monitored, pwstrDeviceId)) {
        MP_VERBOSE(ao, "Already using default device, no reload required\n");
        return S_OK;
    }

    /* if we got here, we need to reload */
    ao_request_reload(ao);
    MP_VERBOSE(ao, "Requesting ao reload\n");
    return S_OK;
}
Exemplo n.º 3
0
static HRESULT STDMETHODCALLTYPE sIMMNotificationClient_OnPropertyValueChanged(
    IMMNotificationClient *This,
    LPCWSTR pwstrDeviceId,
    const PROPERTYKEY key)
{
    change_notify *change = (change_notify *)This;
    struct ao *ao = change->ao;

    if (!change->is_hotplug && pwstrDeviceId &&
        !wcscmp(pwstrDeviceId, change->monitored))
    {
        MP_VERBOSE(ao, "OnPropertyValueChanged triggered on device %S\n",
                   pwstrDeviceId);
        if (IsEqualPropertyKey(PKEY_AudioEngine_DeviceFormat, key)) {
            MP_VERBOSE(change->ao,
                       "Changed property: PKEY_AudioEngine_DeviceFormat "
                       "- requesting ao reload\n");
            ao_request_reload(change->ao);
        } else {
            MP_VERBOSE(ao, "Changed property: %s\n", mp_PKEY_to_str(&key));
        }
    }

    return S_OK;
}
Exemplo n.º 4
0
// Common code for handling ENODEV, which happens if a device gets "lost", and
// can't be used anymore. Returns true if alsa_err is not ENODEV.
static bool check_device_present(struct ao *ao, int alsa_err)
{
    struct priv *p = ao->priv;
    if (alsa_err != -ENODEV)
        return true;
    if (!p->device_lost) {
        MP_WARN(ao, "Device lost, trying to recover...\n");
        ao_request_reload(ao);
        p->device_lost = true;
    }
    return false;
}
Exemplo n.º 5
0
/* maybe MPV can go over to the prefered device once it is plugged in? */
static HRESULT STDMETHODCALLTYPE sIMMNotificationClient_OnDeviceRemoved(
    IMMNotificationClient *This,
    LPCWSTR pwstrDeviceId)
{
    change_notify *change = (change_notify *)This;
    struct ao *ao = change->ao;

    if (pwstrDeviceId && !wcscmp(change->monitored, pwstrDeviceId)) {
        MP_VERBOSE(ao, "OnDeviceRemoved triggered - requesting ao reload\n");
        ao_request_reload(ao);
    }
    return S_OK;
}
Exemplo n.º 6
0
static void stream_state_cb(pa_stream *s, void *userdata)
{
    struct ao *ao = userdata;
    struct priv *priv = ao->priv;
    switch (pa_stream_get_state(s)) {
    case PA_STREAM_FAILED:
        MP_VERBOSE(ao, "Stream failed.\n");
        ao_request_reload(ao);
        pa_threaded_mainloop_signal(priv->mainloop, 0);
        break;
    case PA_STREAM_READY:
    case PA_STREAM_TERMINATED:
        pa_threaded_mainloop_signal(priv->mainloop, 0);
        break;
    }
}
Exemplo n.º 7
0
static void thread_feed(struct ao *ao)
{
    struct wasapi_state *state = ao->priv;
    HRESULT hr;

    UINT32 frame_count = state->bufferFrameCount;

    if (state->share_mode == AUDCLNT_SHAREMODE_SHARED) {
        UINT32 padding = 0;
        hr = IAudioClient_GetCurrentPadding(state->pAudioClient, &padding);
        EXIT_ON_ERROR(hr);

        frame_count -= padding;
        MP_TRACE(ao, "Frame to fill: %"PRIu32". Padding: %"PRIu32"\n",
                 frame_count, padding);
    }
    double delay_us;
    hr = get_device_delay(state, &delay_us);
    EXIT_ON_ERROR(hr);
    // add the buffer delay
    delay_us += frame_count * 1e6 / state->format.Format.nSamplesPerSec;

    BYTE *pData;
    hr = IAudioRenderClient_GetBuffer(state->pRenderClient,
                                      frame_count, &pData);
    EXIT_ON_ERROR(hr);

    BYTE *data[1] = {pData};

    ao_read_data(ao, (void **)data, frame_count,
                 mp_time_us() + (int64_t)llrint(delay_us));

    // note, we can't use ao_read_data return value here since we already
    // commited to frame_count above in the GetBuffer call
    hr = IAudioRenderClient_ReleaseBuffer(state->pRenderClient,
                                          frame_count, 0);
    EXIT_ON_ERROR(hr);

    atomic_fetch_add(&state->sample_count, frame_count);

    return;
exit_label:
    MP_ERR(state, "Error feeding audio: %s\n", mp_HRESULT_to_str(hr));
    MP_VERBOSE(ao, "Requesting ao reload\n");
    ao_request_reload(ao);
    return;
}
Exemplo n.º 8
0
// maybe MPV can go over to the prefered device once it is plugged in?
static HRESULT STDMETHODCALLTYPE sIMMNotificationClient_OnDeviceRemoved(
    IMMNotificationClient *This,
    LPCWSTR pwstrDeviceId)
{
    change_notify *change = (change_notify *)This;
    struct ao *ao = change->ao;

    if (change->is_hotplug) {
        MP_VERBOSE(ao, "OnDeviceRemoved triggered: sending hotplug event\n");
        ao_hotplug_event(ao);
    } else if (pwstrDeviceId && !wcscmp(pwstrDeviceId, change->monitored)) {
        MP_VERBOSE(ao, "OnDeviceRemoved triggered for device %S: "
                   "requesting ao reload\n", pwstrDeviceId);
        ao_request_reload(ao);
    }

    return S_OK;
}
Exemplo n.º 9
0
static HRESULT STDMETHODCALLTYPE sIMMNotificationClient_OnDefaultDeviceChanged(
    IMMNotificationClient *This,
    EDataFlow flow,
    ERole role,
    LPCWSTR pwstrDeviceId)
{
    change_notify *change = (change_notify *)This;
    struct ao *ao = change->ao;

    // don't care about "eCapture" or non-"eMultimedia" roles
    if (flow == eCapture || role != eMultimedia) return S_OK;

    if (change->is_hotplug) {
        MP_VERBOSE(ao,
                   "OnDefaultDeviceChanged triggered: sending hotplug event\n");
        ao_hotplug_event(ao);
    } else {
        // stay on the device the user specified
        bstr device = wasapi_get_specified_device_string(ao);
        if (device.len) {
            MP_VERBOSE(ao, "OnDefaultDeviceChanged triggered: "
                       "staying on specified device %.*s\n", BSTR_P(device));
            return S_OK;
        }

        // don't reload if already on the new default
        if (pwstrDeviceId && !wcscmp(pwstrDeviceId, change->monitored)) {
            MP_VERBOSE(ao, "OnDefaultDeviceChanged triggered: "
                       "already using default device, no reload required\n");
            return S_OK;
        }

        // if we got here, we need to reload
        MP_VERBOSE(ao,
                   "OnDefaultDeviceChanged triggered: requesting ao reload\n");
        ao_request_reload(ao);
    }

    return S_OK;
}
Exemplo n.º 10
0
static HRESULT STDMETHODCALLTYPE sIMMNotificationClient_OnDefaultDeviceChanged(
    IMMNotificationClient *This,
    EDataFlow flow,
    ERole role,
    LPCWSTR pwstrDeviceId)
{
    change_notify *change = (change_notify *)This;
    struct ao *ao = change->ao;
    struct wasapi_state *state = ao->priv;

    /* don't care about "eCapture" or non-"eMultimedia" roles  */
    if (flow == eCapture || role != eMultimedia) return S_OK;

    if (change->is_hotplug) {
        MP_VERBOSE(ao, "OnDefaultDeviceChanged triggered: sending hotplug event\n");
        ao_hotplug_event(ao);
    } else {
        /* stay on the device the user specified */
        if (state->opt_device) {
            MP_VERBOSE(ao, "OnDefaultDeviceChanged triggered: "
                       "staying on specified device %s\n", state->opt_device);
            return S_OK;
        }

        /* don't reload if already on the new default */
        if (pwstrDeviceId && !lstrcmpW(pwstrDeviceId, change->monitored)) {
            MP_VERBOSE(ao, "OnDefaultDeviceChanged triggered: "
                       "already using default device, no reload required\n");
            return S_OK;
        }

        /* if we got here, we need to reload */
        MP_VERBOSE(ao, "OnDefaultDeviceChanged triggered: requesting ao reload\n");
        ao_request_reload(ao);
    }

    return S_OK;
}
Exemplo n.º 11
0
static HRESULT STDMETHODCALLTYPE sIMMNotificationClient_OnDeviceStateChanged(
    IMMNotificationClient *This,
    LPCWSTR pwstrDeviceId,
    DWORD dwNewState)
{
    change_notify *change = (change_notify *)This;
    struct ao *ao = change->ao;

    if (pwstrDeviceId && !wcscmp(change->monitored, pwstrDeviceId)) {
        switch (dwNewState) {
        case DEVICE_STATE_DISABLED:
        case DEVICE_STATE_NOTPRESENT:
        case DEVICE_STATE_UNPLUGGED:
            MP_VERBOSE(ao,
                       "OnDeviceStateChange triggered - requesting ao reload\n");
            ao_request_reload(ao);
        case DEVICE_STATE_ACTIVE:
        default:
            return S_OK;
        }
    }
    return S_OK;
}