text: //
  // libtgvoip is free and unencumbered public domain software.
  // For more information, see http://unlicense.org or the UNLICENSE file
  // you should have received with this source code distribution.
  //
  
  #ifndef LIBTGVOIP_AUDIOINPUTWASAPI_H
  #define LIBTGVOIP_AUDIOINPUTWASAPI_H
  
  #if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP
  #define TGVOIP_WINDOWS_PHONE
  #endif
  #if !defined(WINAPI_FAMILY) || WINAPI_FAMILY==WINAPI_FAMILY_DESKTOP_APP
  #define TGVOIP_WINDOWS_DESKTOP
  #endif
  
  #include <windows.h>
  #include <string>
  #include <vector>
  #pragma warning(push)
  #pragma warning(disable : 4201)
  #ifndef TGVOIP_WP_SILVERLIGHT
  #include <mmdeviceapi.h>
  #endif
  #ifdef TGVOIP_WINDOWS_DESKTOP
  #include <audiopolicy.h>
  #include <functiondiscoverykeys.h>
  #else
  #include <audioclient.h>
  #include "WindowsSandboxUtils.h"
  #endif
  #pragma warning(pop)
  #include "../../audio/AudioInput.h"
  
  namespace tgvoip{
  namespace audio{
  
  #ifdef TGVOIP_WINDOWS_DESKTOP
  class AudioInputWASAPI : public AudioInput, IMMNotificationClient, IAudioSessionEvents{
  #else
  class AudioInputWASAPI : public AudioInput{
  #endif
  
  public:
  	AudioInputWASAPI(std::string deviceID);
  	virtual ~AudioInputWASAPI();
  	virtual void Configure(uint32_t sampleRate, uint32_t bitsPerSample, uint32_t channels);
  	virtual void Start();
  	virtual void Stop();
  	virtual bool IsRecording();
  	virtual void SetCurrentDevice(std::string deviceID);
  	static void EnumerateDevices(std::vector<AudioInputDevice>& devs);
  #ifdef TGVOIP_WINDOWS_DESKTOP
  	STDMETHOD_(ULONG, AddRef)();
  	STDMETHOD_(ULONG, Release)();
  #endif
  
  private:
  	void ActuallySetCurrentDevice(std::string deviceID);
  	static DWORD StartThread(void* arg);
  	void RunThread();
  	WAVEFORMATEX format;
  	bool isRecording;
  	HANDLE shutdownEvent;
  	HANDLE audioSamplesReadyEvent;
  	HANDLE streamSwitchEvent;
  	HANDLE thread;
  	IAudioClient* audioClient;
  	IAudioCaptureClient* captureClient;
  #ifdef TGVOIP_WINDOWS_DESKTOP
  	IMMDeviceEnumerator* enumerator;
  	IAudioSessionControl* audioSessionControl;
  	IMMDevice* device;
  #endif
  	unsigned char remainingData[10240];
  	size_t remainingDataLen;
  	bool isDefaultDevice;
  	ULONG refCount;
  	std::string streamChangeToDevice;
  	bool started;
  
  #ifdef TGVOIP_WINDOWS_DESKTOP
  	STDMETHOD(OnDisplayNameChanged) (LPCWSTR /*NewDisplayName*/, LPCGUID /*EventContext*/) { return S_OK; };
  	STDMETHOD(OnIconPathChanged) (LPCWSTR /*NewIconPath*/, LPCGUID /*EventContext*/) { return S_OK; };
  	STDMETHOD(OnSimpleVolumeChanged) (float /*NewSimpleVolume*/, BOOL /*NewMute*/, LPCGUID /*EventContext*/) { return S_OK; }
  	STDMETHOD(OnChannelVolumeChanged) (DWORD /*ChannelCount*/, float /*NewChannelVolumes*/[], DWORD /*ChangedChannel*/, LPCGUID /*EventContext*/) { return S_OK; };
  	STDMETHOD(OnGroupingParamChanged) (LPCGUID /*NewGroupingParam*/, LPCGUID /*EventContext*/) { return S_OK; };
  	STDMETHOD(OnStateChanged) (AudioSessionState /*NewState*/) { return S_OK; };
  	STDMETHOD(OnSessionDisconnected) (AudioSessionDisconnectReason DisconnectReason);
  	STDMETHOD(OnDeviceStateChanged) (LPCWSTR /*DeviceId*/, DWORD /*NewState*/) { return S_OK; }
  	STDMETHOD(OnDeviceAdded) (LPCWSTR /*DeviceId*/) { return S_OK; };
  	STDMETHOD(OnDeviceRemoved) (LPCWSTR /*DeviceId(*/) { return S_OK; };
  	STDMETHOD(OnDefaultDeviceChanged) (EDataFlow Flow, ERole Role, LPCWSTR NewDefaultDeviceId);
  	STDMETHOD(OnPropertyValueChanged) (LPCWSTR /*DeviceId*/, const PROPERTYKEY /*Key*/) { return S_OK; };
  
  	//
  	//  IUnknown
  	//
  	STDMETHOD(QueryInterface)(REFIID iid, void **pvObject);
  #endif
  };
  
  }
  }
  
  #endif //LIBTGVOIP_AUDIOINPUTWASAPI_H
  