globally remove all trailing whitespace from .cpp and .hpp files missed by previous...
[ardour.git] / libs / backends / wavesaudio / wavesapi / devicemanager / WCMRNativeAudio.cpp
1 //----------------------------------------------------------------------------------
2 //
3 // Copyright (c) 2008 Waves Audio Ltd. All rights reserved.
4 //
5 //! \file       WCMRNativeAudio.cpp
6 //!
7 //! WCMRNativeAudioConnection and related class defienitions
8 //!
9 //---------------------------------------------------------------------------------*/
10 #if defined(__APPLE__)
11 #include <CoreAudio/CoreAudio.h>
12 #endif
13
14 #include "WCMRNativeAudio.h"
15 #include "MiscUtils/pthread_utils.h"
16 #include "MiscUtils/safe_delete.h"
17 #include <iostream>
18 #include <sstream>
19 #include <boost/assign/list_of.hpp>
20
21 #define NONE_DEVICE_NAME "None"
22 #define NONE_DEVICE_INPUT_NAMES "Input "
23 #define NONE_DEVICE_OUTPUT_NAMES "Output "
24
25 //**********************************************************************************************
26 // WCMRNativeAudioNoneDevice::WCMRNativeAudioNoneDevice
27 //
28 //! Constructor for the dummy "None" device. This constructor simply adds supported SRs,
29 //!             buffer sizes, and channels, so that it may look like a real native device to
30 //!             the applications.
31 //!
32 //! \param pManager : The managing device manager - simply passed on to the base class.
33 //!
34 //!
35 //**********************************************************************************************
36 WCMRNativeAudioNoneDevice::WCMRNativeAudioNoneDevice (WCMRAudioDeviceManager *pManager)
37         : WCMRNativeAudioDevice (pManager, false /*useMultiThreading*/)
38 #ifndef PTW32_VERSION
39         , m_SilenceThread(0)
40 #endif
41 #if defined (PLATFORM_WINDOWS)
42     , _waitableTimerForUsleep (CreateWaitableTimer(NULL, TRUE, NULL))
43 #endif
44 {
45         mark_pthread_inactive (m_SilenceThread);
46
47         m_DeviceName = NONE_DEVICE_NAME;
48
49         m_SamplingRates = boost::assign::list_of (m_CurrentSamplingRate=44100)(48000)(88200)(96000)(176400)(192000);
50
51         m_BufferSizes = boost::assign::list_of (32)(64)(128)(m_CurrentBufferSize=256)(512)(1024);
52
53         for (int channel = 0; channel < __m_NumInputChannels; channel++)
54         {
55         std::stringstream name;
56         name << NONE_DEVICE_INPUT_NAMES;
57                 name << (channel + 1);
58                 m_InputChannels.push_back(name.str());
59         }
60
61         for (int channel = 0; channel < __m_NumOutputChannels; channel++)
62         {
63         std::stringstream name;
64         name << NONE_DEVICE_INPUT_NAMES;
65                 name << (channel + 1);
66                 m_OutputChannels.push_back(name.str());
67         }
68         _m_inputBuffer = new float[__m_NumInputChannels * m_BufferSizes.back()];
69         _m_outputBuffer = new float[__m_NumOutputChannels * m_BufferSizes.back()];
70         m_CurrentBufferSize = m_BufferSizes.back();
71 }
72
73
74 WCMRNativeAudioNoneDevice::~WCMRNativeAudioNoneDevice ()
75 {
76 #if defined (PLATFORM_WINDOWS)
77     if(_waitableTimerForUsleep) {
78         CloseHandle(_waitableTimerForUsleep);
79     }
80 #endif
81 }
82
83 WTErr WCMRNativeAudioNoneDevice::SetActive (bool newState)
84 {
85         //This will most likely be overridden, the base class simply
86         //changes the member.
87         if (Active() == newState)
88         {
89                 return (eNoErr);
90         }
91
92         if (Active() && Streaming())
93         {
94                 SetStreaming(false);
95         }
96         return WCMRAudioDevice::SetActive(newState);
97 }
98
99 WTErr WCMRNativeAudioNoneDevice::SetCurrentBufferSize (int newSize)
100 {
101
102         //changes the status.
103         int oldSize = CurrentBufferSize();
104         bool oldActive = Active();
105
106         //same size, nothing to do.
107         if (oldSize == newSize)
108                 return eNoErr;
109         
110         //see if this is one of our supported rates...
111         std::vector<int>::iterator intIter = find(m_BufferSizes.begin(), m_BufferSizes.end(), newSize);
112         if (intIter == m_BufferSizes.end())
113         {
114                 //Can't change, perhaps use an "invalid param" type of error
115                 return eCommandLineParameter;
116         }
117         
118         if (Streaming())
119         {
120                 //Can't change, perhaps use an "in use" type of error
121                 return eGenericErr;
122         }
123
124         
125         return WCMRAudioDevice::SetCurrentBufferSize(newSize);
126 }
127
128
129 WTErr WCMRNativeAudioNoneDevice::UpdateDeviceInfo ()
130 {
131         return eNoErr;
132 }
133
134
135 WTErr WCMRNativeAudioNoneDevice::SetStreaming (bool newState)
136 {
137         if (Streaming() == newState)
138         {
139                 return (eNoErr);
140         }
141
142         WCMRAudioDevice::SetStreaming(newState);
143
144         if (Streaming())
145         {
146                 if (is_pthread_active (m_SilenceThread))
147                         std::cerr << "\t\t\t\t\t !!!!!!!!!!!!!!! Warning: the inactive NONE-DEVICE was streaming!" << std::endl;
148
149                 pthread_attr_t attributes;
150                 size_t stack_size = 100000;
151 #ifdef __APPLE__
152             stack_size = (((stack_size - 1) / PTHREAD_STACK_MIN) + 1) * PTHREAD_STACK_MIN;
153 #endif
154                 if (pthread_attr_init (&attributes)) {
155                         std::cerr << "WCMRNativeAudioNoneDevice::SetStreaming (): pthread_attr_init () failed!" << std::endl;
156                         return eGenericErr;
157                 }
158
159                 if (pthread_attr_setstacksize (&attributes, stack_size)) {
160                         std::cerr << "WCMRNativeAudioNoneDevice::SetStreaming (): pthread_attr_setstacksize () failed!" << std::endl;
161                         return eGenericErr;
162                 }
163
164                 if (pthread_create (&m_SilenceThread, &attributes, __SilenceThread, this)) {
165                         mark_pthread_inactive (m_SilenceThread);
166                         std::cerr << "WCMRNativeAudioNoneDevice::SetStreaming (): pthread_create () failed!" << std::endl;
167                         return eGenericErr;
168                 }
169         }
170         else
171         {
172                 if (!is_pthread_active (m_SilenceThread))
173                 {
174                         std::cerr << "\t\t\t\t\t !!!!!!!!!!!!!!! Warning: the active NONE-DEVICE was NOT streaming!" << std::endl;
175                 }
176
177                 while (is_pthread_active (m_SilenceThread))
178                 {
179                         _usleep(1); //now wait for ended  thread;
180                 }
181         }
182
183         return eNoErr;
184 }
185
186 void WCMRNativeAudioNoneDevice::_SilenceThread()
187 {
188 #if defined(PLATFORM_WINDOWS)
189         float* theInpBuffers[__m_NumInputChannels];
190         for(int i = 0; i < __m_NumInputChannels; ++i)
191         {
192                 theInpBuffers[i] = _m_inputBuffer + m_BufferSizes.back() * i;
193         }
194 #else
195         float* theInpBuffers = _m_inputBuffer;
196 #endif
197
198         const size_t buffer_size = CurrentBufferSize();
199     const uint64_t cyclePeriodNanos = (1000000000.0 * buffer_size) / CurrentSamplingRate();
200
201         struct WCMRAudioDeviceManagerClient::AudioCallbackData audioCallbackData =
202         {
203                 (const float*)theInpBuffers,
204                 _m_outputBuffer,
205                 buffer_size,
206                 0,
207                 0
208         };
209
210         audioCallbackData.acdCycleStartTimeNanos =__get_time_nanos();
211
212     // VERY ROUGH IMPLEMENTATION:
213     while(Streaming()) {
214         
215         uint64_t cycleEndTimeNanos = audioCallbackData.acdCycleStartTimeNanos + cyclePeriodNanos;
216
217                 m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::AudioCallback, (void *)&audioCallbackData);
218                 
219         audioCallbackData.acdSampleTime += buffer_size;
220                 
221                 int64_t timeToSleepUsecs = ((int64_t)cycleEndTimeNanos - (int64_t)__get_time_nanos())/1000;
222                 
223         if (timeToSleepUsecs > 0) {
224             _usleep (timeToSleepUsecs);
225         }
226                 audioCallbackData.acdCycleStartTimeNanos = cycleEndTimeNanos+1;
227     }
228         mark_pthread_inactive (m_SilenceThread);
229 }
230
231 void* WCMRNativeAudioNoneDevice::__SilenceThread(void *This)
232 {
233         ((WCMRNativeAudioNoneDevice*)This)->_SilenceThread();
234         return 0;
235 }
236
237 #if defined(PLATFORM_WINDOWS)
238 void WCMRNativeAudioNoneDevice::_usleep(uint64_t duration_usec)
239 {
240     LARGE_INTEGER ft;
241
242     ft.QuadPart = -(10*duration_usec); // Convert to 100 nanosecond interval, negative value indicates relative time
243
244     SetWaitableTimer(_waitableTimerForUsleep, &ft, 0, NULL, NULL, 0);
245     WaitForSingleObject(_waitableTimerForUsleep, INFINITE);
246 }
247 #endif
248
249 uint64_t
250 WCMRNativeAudioNoneDevice::__get_time_nanos ()
251 {
252 #ifdef __APPLE__
253     // here we exploit the time counting API which is used by the WCMRCoreAudioDeviceManager. However,
254     // the API should be a part of WCMRCoreAudioDeviceManager to give a chance of being tied to the
255     // audio device transport time�.
256     return AudioConvertHostTimeToNanos (AudioGetCurrentHostTime ());
257
258 #elif PLATFORM_WINDOWS
259
260     LARGE_INTEGER Frequency, Count ;
261
262     QueryPerformanceFrequency (&Frequency) ;
263     QueryPerformanceCounter (&Count);
264     return uint64_t ((Count.QuadPart * 1000000000.0 / Frequency.QuadPart));
265 #endif
266 }