diff --git a/DOCS/man/ao.rst b/DOCS/man/ao.rst index 60ba6348b1..5ca960c4ea 100644 --- a/DOCS/man/ao.rst +++ b/DOCS/man/ao.rst @@ -302,19 +302,19 @@ Available audio output drivers are: ``wasapi`` Audio output to the Windows Audio Session API. - ``device=`` - Uses the requested endpoint instead of the system's default audio - endpoint. Both the number and the ID String are valid; the ID String - is guaranteed to not change unless the driver is uninstalled. - - Also supports searching active devices by name. If more than one - device matches the name, refuses loading it. - - To get a list of the valid devices, give ``help`` as the id. The - list is the same as the ``list`` suboption, but stops the player - initialization. ``exclusive`` Requests exclusive, direct hardware access. By definition prevents sound playback of any other program until mpv exits. - ``list`` - Lists all audio endpoints (output devices) present in the system. + ``device=`` + Uses the requested endpoint instead of the system's default audio + endpoint. Both an ordinal number (0,1,2,...) and the GUID + String are valid; the GUID string is guaranteed to not change + unless the driver is uninstalled. + + Also supports searching active devices by human readable name. If more + than one device matches the name, refuses loading it. + + This option is mostly deprecated in favour of the more general + ``--audio-device`` option. That said, ``--audio-device=help`` will give + a list of valid device GUIDs (prefixed with ``wasapi/``), as well as + their human readable names, which should work here. diff --git a/audio/out/ao_wasapi.c b/audio/out/ao_wasapi.c index 8a8d910469..5821409f91 100644 --- a/audio/out/ao_wasapi.c +++ b/audio/out/ao_wasapi.c @@ -253,11 +253,6 @@ static int init(struct ao *ao) if(!wasapi_fill_VistaBlob(state)) MP_WARN(ao, "Error loading thread priority functions\n"); - if (state->opt_list) { - if(!wasapi_enumerate_devices(state->log, NULL, NULL)) - MP_WARN(ao, "Error enumerating devices\n"); - } - if (state->opt_exclusive) { state->share_mode = AUDCLNT_SHAREMODE_EXCLUSIVE; } else { @@ -412,8 +407,7 @@ static int hotplug_init(struct ao *ao) static void list_devs(struct ao *ao, struct ao_device_list *list) { CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); - if(!wasapi_enumerate_devices(mp_null_log, ao, list)) - MP_WARN(ao, "Error enumerating devices\n"); + wasapi_enumerate_devices(ao, list); CoUninitialize(); } @@ -433,8 +427,7 @@ const struct ao_driver audio_out_wasapi = { .priv_size = sizeof(wasapi_state), .options = (const struct m_option[]) { OPT_FLAG("exclusive", opt_exclusive, 0), - OPT_FLAG("list", opt_list, 0), - OPT_STRING_VALIDATE("device", opt_device, 0, wasapi_validate_device), + OPT_STRING("device", opt_device, 0), {NULL}, }, }; diff --git a/audio/out/ao_wasapi_utils.c b/audio/out/ao_wasapi_utils.c index 6ecc6c82a2..eb4350f96d 100755 --- a/audio/out/ao_wasapi_utils.c +++ b/audio/out/ao_wasapi_utils.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -96,12 +97,14 @@ const char *wasapi_explain_err(const HRESULT hr) #define E(x) case x : return # x ; switch (hr) { E(S_OK) + E(S_FALSE) E(E_FAIL) E(E_OUTOFMEMORY) E(E_POINTER) E(E_HANDLE) E(E_NOTIMPL) E(E_INVALIDARG) + E(E_PROP_ID_UNSUPPORTED) E(REGDB_E_IIDNOTREG) E(CO_E_NOTINITIALIZED) E(AUDCLNT_E_NOT_INITIALIZED) @@ -826,96 +829,62 @@ end: return found; } -// Warning: ao and list are NULL in the "--ao=wasapi:device=help" path! -static HRESULT enumerate_with_state(struct mp_log *log, struct ao *ao, - struct ao_device_list *list, - char *header, int status, int with_id) +HRESULT wasapi_enumerate_devices(struct ao *ao, + struct ao_device_list *list) { - HRESULT hr; IMMDeviceEnumerator *pEnumerator = NULL; IMMDeviceCollection *pDevices = NULL; IMMDevice *pDevice = NULL; - char *defid = NULL; - - hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, - &IID_IMMDeviceEnumerator, (void **)&pEnumerator); + char *name = NULL, *id = NULL; + HRESULT hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, + &IID_IMMDeviceEnumerator, + (void **)&pEnumerator); EXIT_ON_ERROR(hr); - hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(pEnumerator, - eRender, eMultimedia, - &pDevice); - EXIT_ON_ERROR(hr); - - defid = get_device_id(pDevice); - - SAFE_RELEASE(pDevice, IMMDevice_Release(pDevice)); - hr = IMMDeviceEnumerator_EnumAudioEndpoints(pEnumerator, eRender, - status, &pDevices); + DEVICE_STATE_ACTIVE, &pDevices); EXIT_ON_ERROR(hr); int count; - IMMDeviceCollection_GetCount(pDevices, &count); + hr = IMMDeviceCollection_GetCount(pDevices, &count); + EXIT_ON_ERROR(hr); if (count > 0) - mp_info(log, "%s\n", header); + MP_VERBOSE(ao, "Output devices:\n"); for (int i = 0; i < count; i++) { hr = IMMDeviceCollection_Item(pDevices, i, &pDevice); EXIT_ON_ERROR(hr); - char *name = get_device_name(pDevice); - char *id = get_device_id(pDevice); - - char *mark = ""; - if (strcmp(id, defid) == 0) - mark = " (default)"; - - if (with_id) { - mp_info(log, "Device #%d: %s, ID: %s%s\n", i, name, id, mark); - } else { - mp_info(log, "%s, ID: %s%s\n", name, id, mark); + name = get_device_name(pDevice); + id = get_device_id(pDevice); + if (!id) { + hr = E_FAIL; + EXIT_ON_ERROR(hr); } + char *safe_name = name ? name : ""; + ao_device_list_add(list, ao, &(struct ao_device_desc){id, safe_name}); - if (ao) { - char *desc = talloc_asprintf(NULL, "%s, ID: %s%s", name, id, mark); - struct ao_device_desc e = {id, desc}; - ao_device_list_add(list, ao, &e); - } + MP_VERBOSE(ao, "#%d, GUID: \'%s\', name: \'%s\'\n", i, id, safe_name); talloc_free(name); talloc_free(id); SAFE_RELEASE(pDevice, IMMDevice_Release(pDevice)); } - talloc_free(defid); SAFE_RELEASE(pDevices, IMMDeviceCollection_Release(pDevices)); SAFE_RELEASE(pEnumerator, IMMDeviceEnumerator_Release(pEnumerator)); return S_OK; exit_label: - talloc_free(defid); + MP_ERR(ao, "Error enumerating devices: %s (0x%"PRIx32")\n", + wasapi_explain_err(hr), (uint32_t) hr); + talloc_free(name); + talloc_free(id); SAFE_RELEASE(pDevice, IMMDevice_Release(pDevice)); SAFE_RELEASE(pDevices, IMMDeviceCollection_Release(pDevices)); SAFE_RELEASE(pEnumerator, IMMDeviceEnumerator_Release(pEnumerator)); return hr; } -bool wasapi_enumerate_devices(struct mp_log *log, struct ao *ao, - struct ao_device_list *list) -{ - HRESULT hr; - hr = enumerate_with_state(log, ao, list, "Active devices:", - DEVICE_STATE_ACTIVE, 1); - EXIT_ON_ERROR(hr); - hr = enumerate_with_state(log, ao, list, "Unplugged devices:", - DEVICE_STATE_UNPLUGGED, 0); - EXIT_ON_ERROR(hr); - return true; -exit_label: - mp_err(log, "Error enumerating devices: %s (0x%"PRIx32")\n", - wasapi_explain_err(hr), (uint32_t) hr); - return false; -} - static HRESULT load_default_device(struct ao *ao, IMMDeviceEnumerator* pEnumerator, IMMDevice **ppDevice) { @@ -1043,27 +1012,6 @@ exit_label: return hr; } -int wasapi_validate_device(struct mp_log *log, const m_option_t *opt, - struct bstr name, struct bstr param) -{ - if (bstr_equals0(param, "help")) { - wasapi_enumerate_devices(log, NULL, NULL); - return M_OPT_EXIT; - } - - mp_dbg(log, "Validating device=%s\n", param.start); - - char *end; - int devno = (int) strtol(param.start, &end, 10); - - int ret = 1; - if ((end == (void *)param.start || *end) && devno < 0) - ret = M_OPT_OUT_OF_RANGE; - - mp_dbg(log, "device=%s %svalid\n", param.start, ret == 1 ? "" : "not "); - return ret; -} - HRESULT wasapi_setup_proxies(struct wasapi_state *state) { HRESULT hr; diff --git a/audio/out/ao_wasapi_utils.h b/audio/out/ao_wasapi_utils.h index 7327d2f350..9806bba4a9 100755 --- a/audio/out/ao_wasapi_utils.h +++ b/audio/out/ao_wasapi_utils.h @@ -36,12 +36,8 @@ bool wasapi_fill_VistaBlob(wasapi_state *state); const char *wasapi_explain_err(const HRESULT hr); -bool wasapi_enumerate_devices(struct mp_log *log, struct ao *ao, - struct ao_device_list *list); - -int wasapi_validate_device(struct mp_log *log, const m_option_t *opt, - struct bstr name, struct bstr param); - +HRESULT wasapi_enumerate_devices(struct ao *ao, + struct ao_device_list *list); void wasapi_dispatch(void); HRESULT wasapi_thread_init(struct ao *ao);