summaryrefslogtreecommitdiff
path: root/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRPortAudioDeviceManager.h
blob: da2027466e572378e1afe92f1515fa13c53d00d7 (plain)
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
/*
    Copyright (C) 2014 Waves Audio Ltd.

    This program 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.

    This program 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 this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

*/

//----------------------------------------------------------------------------------
//
//
//! \file	WCMRPortAudioDeviceManager.h
//!
//! WCMRPortAudioDeviceManager and related class declarations
//!
//---------------------------------------------------------------------------------*/
#ifndef __WCMRPortAudioDeviceManager_h_
	#define __WCMRPortAudioDeviceManager_h_

#include "WCMRAudioDeviceManager.h"
#include "WCMRNativeAudio.h"
#include "portaudio.h"

//forward decl.
class WCMRPortAudioDeviceManager;

//! Manages a port audio device, providing information
//! about the device, and managing audio callbacks.
class WCMRPortAudioDevice : public WCMRNativeAudioDevice
{
public:

	WCMRPortAudioDevice (WCMRPortAudioDeviceManager *pManager, unsigned int  deviceID, bool useMultiThreading = true, bool bNoCopy = false);///<Constructor
	virtual ~WCMRPortAudioDevice ();///<Destructor

	virtual int CurrentSamplingRate(); ///<Current Sampling rate.?
	virtual WTErr SetCurrentSamplingRate(int newRate);///<Change Current Sampling Rate : This is a requset, might not be successful at run time!

	virtual int CurrentBufferSize();///<Current Buffer Size.? - note that this may change with change in sampling rate.
	virtual WTErr SetCurrentBufferSize (int newSize);///<Change Current Buffer Size : This is a requset, might not be successful at run time!

	virtual ConnectionStates ConnectionStatus();///< Connection Status - device available, gone, disconnected

	virtual WTErr SetActive (bool newState);///<Prepare/Activate device.
	
	virtual WTErr SetStreaming (bool newState);///<Start/Stop Streaming - should reconnect connections when streaming starts!

	virtual WTErr SetMonitorChannels (int leftChannel, int rightChannel);///<Set monitor channels. - optional, will not be available with AG
	virtual WTErr SetMonitorGain (float newGain);///<Set monitor gain. - optional, will not be available with AG
	
	virtual WTErr ShowConfigPanel (void *pParam);///< Show Control Panel - in case of ASIO this will work only with Active device!

	virtual int AudioCallback (const float *pInputBuffer, float *pOutputBuffer, unsigned long framesPerBuffe, bool dropsDetectedr);

	virtual WTErr UpdateDeviceInfo ();

	virtual WTErr ResetDevice();

#ifdef PLATFORM_WINDOWS
	static long StaticASIOMessageHook (void *pRefCon, long selector, long value, void* message, double* opt);
	long ASIOMessageHook (long selector, long value, void* message, double* opt);
#endif //PLATFORM_WINDOWS
	
protected:
	static DWORD WINAPI __DoIdle__(LPVOID lpThreadParameter);

	// Methods which are executed by device processing thread
	WTErr DoIdle();///<Do Idle Processing
	void initDevice();
	void terminateDevice();
	void updateDeviceInfo(bool callerIsWaiting = false);
	void activateDevice(bool callerIsWaiting = false);
	void deactivateDevice(bool callerIsWaiting = false);
	void startStreaming(bool callerIsWaiting = false);
	void stopStreaming(bool callerIsWaiting = false);
	void resetDevice (bool callerIsWaiting = false);///<Reset device - close and reopen stream, update device information!

	PaError testStateValidness(int sampleRate, int bufferSize);
	///////////////////////////////////////////////////////////
	
	static int TheCallback (const void *pInputBuffer, void *pOutputBuffer, unsigned long framesPerBuffer, 
							const PaStreamCallbackTimeInfo* /*pTimeInfo*/, PaStreamCallbackFlags /*statusFlags*/, void *pUserData );

	unsigned int m_DeviceID; ///< The PA device id
	PaStream* m_PortAudioStream; ///< Port audio stream, when the device is active!
	bool m_StopRequested; ///< should be set to true when want to stop, set to false otherwise.
	const float *m_pInputData; ///< This is what came in with the most recent callback.
	int64_t m_SampleCounter; ///< The current running sample counter, updated by the audio callback.
	int64_t m_SampleCountAtLastIdle;

	int m_DropsDetected; ///< Number of times audio drops have been detected so far.
	int m_DropsReported; ///< Number of times audio drops have been reported so far to the client.
	bool m_IgnoreThisDrop; ///< Allows disregarding the first drop

	int m_BufferSizeChangeRequested;
	int m_BufferSizeChangeReported;
	int m_ResetRequested;
	int m_ResetReported;
	int m_ResyncRequested;
	int m_ResyncReported;

	HANDLE m_hDeviceProcessingThread;
	DWORD m_DeviceProcessingThreadID;

	///< Backend request events
	HANDLE m_hResetRequestedEvent;
	HANDLE m_hResetDone;

	HANDLE m_hUpdateDeviceInfoRequestedEvent;
	HANDLE m_hUpdateDeviceInfoDone;

	HANDLE m_hActivateRequestedEvent;
	HANDLE m_hActivationDone;

	HANDLE m_hDeActivateRequestedEvent;
	HANDLE m_hDeActivationDone;

	HANDLE m_hStartStreamingRequestedEvent;
	HANDLE m_hStartStreamingDone;

	HANDLE m_hStopStreamingRequestedEvent;
	HANDLE m_hStopStreamingDone;
	/////////////////////////

	///< Device request events
	HANDLE m_hResetFromDevRequestedEvent;
	HANDLE m_hBufferSizeChangedEvent;
	HANDLE m_hSampleRateChangedEvent;
	/////////////////////////////

	///< Sync events
	HANDLE m_hDeviceInitialized;
	HANDLE m_hExitIdleThread;

	//Should be set if the device connection status is "DeviceErrors"
	WTErr m_lastErr;
};

//! WCMRPortAudioDeviceManager
/*! The PortAudio Device Manager class */
class WCMRPortAudioDeviceManager : public WCMRAudioDeviceManager
{
public:
	WCMRPortAudioDeviceManager(WCMRAudioDeviceManagerClient *pTheClient, eAudioDeviceFilter eCurAudioDeviceFilter,
								bool useMultithreading = true, bool bNocopy = false); ///< constructor
	
	virtual ~WCMRPortAudioDeviceManager(void); ///< destructor

protected:

	virtual WCMRAudioDevice*	initNewCurrentDeviceImpl(const std::string & deviceName);
	virtual void				destroyCurrentDeviceImpl();
	virtual WTErr				generateDeviceListImpl(); // use this in derived class to fill device list
	virtual WTErr				updateDeviceListImpl() {return eNoErr; } // not supported
	virtual WTErr				getDeviceBufferSizesImpl(const std::string & deviceName, std::vector<int>& buffers) const;
    virtual WTErr				getDeviceSampleRatesImpl(const std::string & deviceName, std::vector<int>& sampleRates) const;

	bool m_UseMultithreading; ///< Flag indicates whether to use multi-threading for audio processing.
    bool m_bNoCopyAudioBuffer;

private:
	// helper functions for this class only
    WTErr getDeviceAvailableSampleRates(DeviceID deviceId, std::vector<int>& sampleRates);
	WTErr getDeviceAvailableBufferSizes(DeviceID deviceId, std::vector<int>& buffers);

	WCMRAudioDevice*			m_NoneDevice;
};

#endif //#ifndef __WCMRPortAudioDeviceManager_h_