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