2014-03-09 23:13:36 +00:00
|
|
|
/*
|
|
|
|
* 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 General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 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 General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License along
|
|
|
|
* with mpv. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef MP_AO_WASAPI_H_
|
|
|
|
#define MP_AO_WASAPI_H_
|
|
|
|
|
2015-03-31 08:56:17 +00:00
|
|
|
#include <stdbool.h>
|
2014-03-09 23:13:36 +00:00
|
|
|
#include <audioclient.h>
|
2014-03-11 06:46:22 +00:00
|
|
|
#include <audiopolicy.h>
|
2014-03-09 23:13:36 +00:00
|
|
|
#include <mmdeviceapi.h>
|
|
|
|
#include <avrt.h>
|
|
|
|
|
2014-08-29 10:09:04 +00:00
|
|
|
#include "osdep/atomics.h"
|
2014-05-20 23:04:47 +00:00
|
|
|
|
2014-11-17 11:37:51 +00:00
|
|
|
typedef struct change_notify {
|
2014-11-13 09:09:47 +00:00
|
|
|
IMMNotificationClient client; /* this must be first in the structure! */
|
2014-11-17 11:37:51 +00:00
|
|
|
LPWSTR monitored; /* Monitored device */
|
2015-03-31 08:56:17 +00:00
|
|
|
bool is_hotplug;
|
2014-11-13 09:09:47 +00:00
|
|
|
struct ao *ao;
|
2014-11-17 11:37:51 +00:00
|
|
|
} change_notify;
|
|
|
|
|
2015-03-31 08:56:17 +00:00
|
|
|
HRESULT wasapi_change_init(struct ao* ao, bool is_hotplug);
|
2014-11-13 09:09:47 +00:00
|
|
|
void wasapi_change_uninit(struct ao* ao);
|
|
|
|
|
|
|
|
#define EXIT_ON_ERROR(hres) \
|
|
|
|
do { if (FAILED(hres)) { goto exit_label; } } while(0)
|
|
|
|
#define SAFE_RELEASE(unk, release) \
|
|
|
|
do { if ((unk) != NULL) { release; (unk) = NULL; } } while(0)
|
2014-11-17 11:37:51 +00:00
|
|
|
|
2015-03-29 00:12:48 +00:00
|
|
|
enum wasapi_thread_state {
|
|
|
|
WASAPI_THREAD_FEED = 0,
|
|
|
|
WASAPI_THREAD_RESUME,
|
|
|
|
WASAPI_THREAD_RESET,
|
|
|
|
WASAPI_THREAD_SHUTDOWN
|
|
|
|
};
|
|
|
|
|
2014-03-09 23:13:36 +00:00
|
|
|
typedef struct wasapi_state {
|
|
|
|
struct mp_log *log;
|
|
|
|
/* Init phase */
|
2014-11-17 10:48:02 +00:00
|
|
|
HRESULT init_ret;
|
2015-03-29 00:12:48 +00:00
|
|
|
HANDLE hInitDone;
|
2014-03-09 23:13:36 +00:00
|
|
|
int share_mode;
|
|
|
|
|
|
|
|
/* volume control */
|
2015-03-27 23:48:39 +00:00
|
|
|
DWORD vol_hw_support;
|
2014-03-09 23:13:36 +00:00
|
|
|
float audio_volume;
|
2014-03-11 05:50:49 +00:00
|
|
|
float previous_volume;
|
|
|
|
float initial_volume;
|
2014-03-09 23:13:36 +00:00
|
|
|
|
2015-03-27 23:48:39 +00:00
|
|
|
/* WASAPI handles, owned by audio thread */
|
2014-03-09 23:13:36 +00:00
|
|
|
IMMDevice *pDevice;
|
|
|
|
IAudioClient *pAudioClient;
|
|
|
|
IAudioRenderClient *pRenderClient;
|
2014-03-11 05:50:49 +00:00
|
|
|
ISimpleAudioVolume *pAudioVolume;
|
2014-03-09 23:13:36 +00:00
|
|
|
IAudioEndpointVolume *pEndpointVolume;
|
2014-03-11 06:46:22 +00:00
|
|
|
IAudioSessionControl *pSessionControl;
|
2014-11-13 09:09:47 +00:00
|
|
|
IMMDeviceEnumerator *pEnumerator;
|
|
|
|
|
2015-03-27 23:48:39 +00:00
|
|
|
/* thread handles */
|
2015-03-29 00:12:48 +00:00
|
|
|
HANDLE hAudioThread; /* the thread itself */
|
|
|
|
HANDLE hWake; /* thread wakeup event */
|
|
|
|
atomic_int thread_state; /* enum wasapi_thread_state */
|
2015-03-27 23:48:39 +00:00
|
|
|
|
|
|
|
/* for setting the audio thread priority */
|
2014-03-09 23:13:36 +00:00
|
|
|
HANDLE hTask; /* AV thread */
|
|
|
|
|
2014-03-11 03:47:33 +00:00
|
|
|
/* WASAPI proxy handles, for Single-Threaded Apartment communication.
|
2015-03-27 23:48:39 +00:00
|
|
|
One is needed for each audio thread object that's accessed from the main thread. */
|
2014-03-11 05:50:49 +00:00
|
|
|
ISimpleAudioVolume *pAudioVolumeProxy;
|
2014-03-11 03:47:33 +00:00
|
|
|
IAudioEndpointVolume *pEndpointVolumeProxy;
|
2014-03-11 06:46:22 +00:00
|
|
|
IAudioSessionControl *pSessionControlProxy;
|
2014-03-11 03:47:33 +00:00
|
|
|
|
|
|
|
/* Streams used to marshal the proxy objects. The thread owning the actual objects
|
|
|
|
needs to marshal proxy objects into these streams, and the thread that wants the
|
|
|
|
proxies unmarshals them from here. */
|
2014-03-11 05:50:49 +00:00
|
|
|
IStream *sAudioVolume;
|
2014-03-11 03:47:33 +00:00
|
|
|
IStream *sEndpointVolume;
|
2014-03-11 06:46:22 +00:00
|
|
|
IStream *sSessionControl;
|
2014-03-11 03:47:33 +00:00
|
|
|
|
2014-03-09 23:13:36 +00:00
|
|
|
/* WASAPI internal clock information, for estimating delay */
|
|
|
|
IAudioClock *pAudioClock;
|
|
|
|
UINT64 clock_frequency; /* scale for the "samples" returned by the clock */
|
2014-05-20 23:04:47 +00:00
|
|
|
atomic_ullong sample_count; /* the amount of samples per channel written to a GetBuffer buffer */
|
2014-03-09 23:13:36 +00:00
|
|
|
LARGE_INTEGER qpc_frequency; /* frequency of windows' high resolution timer */
|
|
|
|
|
2015-03-27 23:48:39 +00:00
|
|
|
/* ao options */
|
2014-03-09 23:13:36 +00:00
|
|
|
int opt_exclusive;
|
|
|
|
int opt_list;
|
|
|
|
char *opt_device;
|
|
|
|
|
2015-03-27 23:48:39 +00:00
|
|
|
/* format info */
|
|
|
|
WAVEFORMATEXTENSIBLE format;
|
|
|
|
size_t buffer_block_size; /* Size of each block in bytes */
|
|
|
|
UINT32 bufferFrameCount; /* wasapi buffer block size, number of frames, frame size at format.nBlockAlign */
|
|
|
|
|
2014-11-13 09:09:47 +00:00
|
|
|
change_notify change;
|
2014-03-09 23:13:36 +00:00
|
|
|
} wasapi_state;
|
|
|
|
|
2014-03-11 03:47:33 +00:00
|
|
|
#endif
|