1 /* 2 * This file is part of mpv. 3 * 4 * Original author: Jonathan Yong <10walls@gmail.com> 5 * 6 * mpv is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * mpv is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with mpv. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 #ifndef MP_AO_WASAPI_H_ 21 #define MP_AO_WASAPI_H_ 22 23 #include <stdlib.h> 24 #include <stdbool.h> 25 #include <windows.h> 26 #include <mmdeviceapi.h> 27 #include <audioclient.h> 28 #include <audiopolicy.h> 29 #include <endpointvolume.h> 30 31 #include "common/msg.h" 32 #include "osdep/atomic.h" 33 #include "osdep/windows_utils.h" 34 #include "internal.h" 35 #include "ao.h" 36 37 typedef struct change_notify { 38 IMMNotificationClient client; // this must be first in the structure! 39 IMMDeviceEnumerator *pEnumerator; // object where client is registered 40 LPWSTR monitored; // Monitored device 41 bool is_hotplug; 42 struct ao *ao; 43 } change_notify; 44 45 HRESULT wasapi_change_init(struct ao* ao, bool is_hotplug); 46 void wasapi_change_uninit(struct ao* ao); 47 48 enum wasapi_thread_state { 49 WASAPI_THREAD_FEED = 0, 50 WASAPI_THREAD_RESUME, 51 WASAPI_THREAD_RESET, 52 WASAPI_THREAD_SHUTDOWN 53 }; 54 55 typedef struct wasapi_state { 56 struct mp_log *log; 57 58 bool init_ok; // status of init phase 59 // Thread handles 60 HANDLE hInitDone; // set when init is complete in audio thread 61 HANDLE hAudioThread; // the audio thread itself 62 HANDLE hWake; // thread wakeup event 63 atomic_int thread_state; // enum wasapi_thread_state (what to do on wakeup) 64 struct mp_dispatch_queue *dispatch; // for volume/mute/session display 65 66 // for setting the audio thread priority 67 HANDLE hTask; 68 69 // ID of the device to use 70 LPWSTR deviceID; 71 // WASAPI object handles owned and used by audio thread 72 IMMDevice *pDevice; 73 IAudioClient *pAudioClient; 74 IAudioRenderClient *pRenderClient; 75 76 // WASAPI internal clock information, for estimating delay 77 IAudioClock *pAudioClock; 78 atomic_ullong sample_count; // samples per channel written by GetBuffer 79 UINT64 clock_frequency; // scale for position returned by GetPosition 80 LARGE_INTEGER qpc_frequency; // frequency of Windows' high resolution timer 81 82 // WASAPI control 83 IAudioSessionControl *pSessionControl; // setting the stream title 84 IAudioEndpointVolume *pEndpointVolume; // exclusive mode volume/mute 85 ISimpleAudioVolume *pAudioVolume; // shared mode volume/mute 86 DWORD vol_hw_support; // is hardware volume supported for exclusive-mode? 87 88 // ao options 89 int opt_exclusive; 90 91 // format info 92 WAVEFORMATEXTENSIBLE format; 93 AUDCLNT_SHAREMODE share_mode; // AUDCLNT_SHAREMODE_EXCLUSIVE / SHARED 94 UINT32 bufferFrameCount; // number of frames in buffer 95 struct ao_convert_fmt convert_format; 96 97 change_notify change; 98 } wasapi_state; 99 100 char *mp_PKEY_to_str_buf(char *buf, size_t buf_size, const PROPERTYKEY *pkey); 101 #define mp_PKEY_to_str(pkey) mp_PKEY_to_str_buf((char[42]){0}, 42, (pkey)) 102 103 void wasapi_list_devs(struct ao *ao, struct ao_device_list *list); 104 bstr wasapi_get_specified_device_string(struct ao *ao); 105 LPWSTR wasapi_find_deviceID(struct ao *ao); 106 107 bool wasapi_thread_init(struct ao *ao); 108 void wasapi_thread_uninit(struct ao *ao); 109 110 #define EXIT_ON_ERROR(hres) \ 111 do { if (FAILED(hres)) { goto exit_label; } } while(0) 112 #define SAFE_DESTROY(unk, release) \ 113 do { if ((unk) != NULL) { release; (unk) = NULL; } } while(0) 114 115 #endif 116