small round of compiler warning fixes
[ardour.git] / libs / backends / wavesaudio / waves_audiobackend.cc
1 /*
2     Copyright (C) 2014 Waves Audio Ltd.
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #include "waves_audiobackend.h"
21 #include "waves_audioport.h"
22 #include "waves_midiport.h"
23
24 using namespace ARDOUR;
25
26 #if defined __MINGW64__ || defined __MINGW32__
27         extern "C" __declspec(dllexport) ARDOUR::AudioBackendInfo* descriptor ()
28 #else
29         extern "C" ARDOURBACKEND_API ARDOUR::AudioBackendInfo* descriptor ()
30 #endif
31 {
32     // COMMENTED DBG LOGS */ std::cout  << "waves_backend.dll : ARDOUR::AudioBackendInfo* descriptor (): " << std::endl;
33     return &WavesAudioBackend::backend_info ();
34 }
35
36 void WavesAudioBackend::AudioDeviceManagerNotification (NotificationReason reason, void* parameter)
37 {
38     switch (reason) {
39         case WCMRAudioDeviceManagerClient::DeviceDebugInfo:
40             std::cout << "-------------------------------  WCMRAudioDeviceManagerClient::DeviceDebugInfo -- " << (char*)parameter << std::endl;
41             break;
42         case WCMRAudioDeviceManagerClient::BufferSizeChanged:
43             std::cout << "-------------------------------  WCMRAudioDeviceManagerClient::BufferSizeChanged: " << *(uint32_t*)parameter << std::endl;
44                         _buffer_size_change(*(uint32_t*)parameter);
45             break;
46         case WCMRAudioDeviceManagerClient::RequestReset:
47             std::cout << "-------------------------------  WCMRAudioDeviceManagerClient::RequestReset" << std::endl;
48             engine.request_backend_reset();
49             break;
50         case WCMRAudioDeviceManagerClient::RequestResync:
51             std::cout << "-------------------------------  WCMRAudioDeviceManagerClient::RequestResync" << std::endl;
52             break;
53         case WCMRAudioDeviceManagerClient::SamplingRateChanged:
54             std::cout << "-------------------------------  WCMRAudioDeviceManagerClient::SamplingRateChanged: " << *(float*)parameter << std::endl;
55                         set_sample_rate(*(float*)parameter);
56             break;
57         case WCMRAudioDeviceManagerClient::Dropout:
58             std::cout << "-------------------------------  WCMRAudioDeviceManagerClient::Dropout: " << std::endl;
59             break;
60         case WCMRAudioDeviceManagerClient::DeviceDroppedSamples:
61             std::cout << "-------------------------------  WCMRAudioDeviceManagerClient::DeviceDroppedSamples" << std::endl;
62             break;
63         case WCMRAudioDeviceManagerClient::DeviceStoppedStreaming:
64             std::cout << "-------------------------------  WCMRAudioDeviceManagerClient::DeviceStoppedStreaming" << std::endl;
65             break;
66                 case WCMRAudioDeviceManagerClient::DeviceStartsStreaming:
67             std::cout << "-------------------------------  WCMRAudioDeviceManagerClient::DeviceStartsStreaming" << std::endl;
68                         _call_thread_init_callback = true; // streaming will be started from device side, just set thread init flag
69             break;
70         case WCMRAudioDeviceManagerClient::DeviceConnectionLost:
71             std::cout << "-------------------------------  WCMRAudioDeviceManagerClient::DeviceConnectionLost" << std::endl;
72             break;
73         case WCMRAudioDeviceManagerClient::DeviceListChanged:
74             std::cout << "-------------------------------  WCMRAudioDeviceManagerClient::DeviceListChanged" << std::endl;
75             engine.request_device_list_update();
76             break;
77         case WCMRAudioDeviceManagerClient::IODeviceDisconnected:
78             std::cout << "-------------------------------  WCMRAudioDeviceManagerClient::DeviceListChanged" << std::endl;
79             engine.request_device_list_update();
80             break;
81         case WCMRAudioDeviceManagerClient::AudioCallback:
82             if (parameter) {
83                 AudioCallbackData* audio_callback_data = (AudioCallbackData*)parameter;
84                 _audio_device_callback (
85                     audio_callback_data->acdInputBuffer,
86                     audio_callback_data->acdOutputBuffer,
87                     audio_callback_data->acdFrames,
88                     audio_callback_data->acdSampleTime,
89                     audio_callback_data->acdCycleStartTimeNanos
90                 );
91             }
92         break;
93         
94         default:
95         break;
96     };
97 }
98
99
100 WavesAudioBackend::WavesAudioBackend (AudioEngine& e)
101     : AudioBackend (e, __backend_info)
102     , _audio_device_manager (this)
103     , _midi_device_manager (*this)
104     , _device (NULL)
105     , _sample_format (FormatFloat)
106     , _interleaved (true)
107     , _input_channels (0)
108     , _max_input_channels (0)
109     , _output_channels (0)
110     , _max_output_channels (0)
111     , _sample_rate (0)
112     , _buffer_size (0)
113     , _systemic_input_latency (0)
114     , _systemic_output_latency (0)
115     , _call_thread_init_callback (false)
116     , _use_midi (true)
117     , _sample_time_at_cycle_start (0)
118     , _freewheeling (false)
119     , _freewheel_thread_active (false)
120     , _dsp_load_accumulator (0)
121     , _audio_cycle_period_nanos (0)
122     , _dsp_load_history_length(0)
123 {
124 }
125
126
127 WavesAudioBackend::~WavesAudioBackend ()
128 {
129     
130 }
131
132 std::string
133 WavesAudioBackend::name () const
134 {
135 #ifdef __APPLE__
136     return std::string ("CoreAudio");
137 #elif PLATFORM_WINDOWS
138     return std::string ("ASIO");
139 #endif
140 }
141
142
143 bool
144 WavesAudioBackend::is_realtime () const
145 {
146     return true;
147 }
148
149
150 bool 
151 WavesAudioBackend::requires_driver_selection () const
152
153     return false; 
154 }
155
156
157 std::vector<std::string> 
158 WavesAudioBackend::enumerate_drivers () const
159
160     // this backend does not suppose driver selection
161     assert (false);
162
163     return std::vector<std::string> (); 
164 }
165
166
167 int 
168 WavesAudioBackend::set_driver (const std::string& /*drivername*/)
169 {
170     //Waves audio backend does not suppose driver selection
171     assert (false);
172
173     return -1; 
174 }
175
176
177 std::vector<AudioBackend::DeviceStatus> 
178 WavesAudioBackend::enumerate_devices () const
179 {   
180     // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::enumerate_devices (): " << std::endl;
181
182     std::vector<DeviceStatus> devicesStatus;
183     const DeviceInfoVec& deviceInfoList = _audio_device_manager.DeviceInfoList(); 
184
185     for (DeviceInfoVecConstIter deviceInfoIter = deviceInfoList.begin ();  deviceInfoIter != deviceInfoList.end (); ++deviceInfoIter) {
186         // COMMENTED DBG LOGS */ std::cout << "\t Device found: " << (*deviceInfoIter)->m_DeviceName << std::endl;
187         devicesStatus.push_back (DeviceStatus ((*deviceInfoIter)->m_DeviceName, true));
188     }
189     
190     return devicesStatus;
191
192
193
194 std::vector<float> 
195 WavesAudioBackend::available_sample_rates (const std::string& device_name) const
196 {
197     // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::available_sample_rates (): [" << device_name << "]" << std::endl;
198
199     std::vector<int> sr;
200     
201     WTErr retVal = _audio_device_manager.GetDeviceSampleRates(device_name, sr);
202     
203         if (eNoErr != retVal) {
204         std::cerr << "WavesAudioBackend::available_sample_rates (): Failed to find device [" << device_name << "]" << std::endl;
205         return std::vector<float> ();
206     }
207
208     // COMMENTED DBG LOGS */ std::cout << "\tFound " << devInfo.m_AvailableSampleRates.size () << " sample rates for " << device_name << ":";
209
210     std::vector<float> sample_rates (sr.begin (), sr.end ());
211     
212     // COMMENTED DBG LOGS */ for (std::vector<float>::iterator i = sample_rates.begin ();  i != sample_rates.end (); ++i) std::cout << " " << *i; std::cout << std::endl;
213
214     return sample_rates;
215 }
216
217
218 float WavesAudioBackend::default_sample_rate () const 
219
220     // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::default_sample_rate (): " << AudioBackend::default_sample_rate () << std::endl;
221     return AudioBackend::default_sample_rate (); 
222 }
223
224
225 std::vector<uint32_t> 
226 WavesAudioBackend::available_buffer_sizes (const std::string& device_name) const
227 {
228     // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::available_buffer_sizes (): [" << device_name << "]" << std::endl;
229
230         std::vector<int> bs;
231
232         WTErr retVal = _audio_device_manager.GetDeviceBufferSizes(device_name, bs);
233
234     if (retVal != eNoErr) {
235         std::cerr << "WavesAudioBackend::available_buffer_sizes (): Failed to get buffer size for device [" << device_name << "]" << std::endl;
236         return std::vector<uint32_t> ();
237     }
238
239     std::vector<uint32_t> buffer_sizes (bs.begin (), bs.end ());
240
241     // COMMENTED DBG LOGS */ std::cout << "\tFound " << buffer_sizes.size () << " buffer sizes for " << device_name << ":";
242     // COMMENTED DBG LOGS */ for (std::vector<uint32_t>::const_iterator i = buffer_sizes.begin ();  i != buffer_sizes.end (); ++i) std::cout << " " << *i; std::cout << std::endl;
243
244     return buffer_sizes;
245 }
246
247
248 uint32_t 
249 WavesAudioBackend::available_input_channel_count (const std::string& device_name) const
250 {
251     DeviceInfo devInfo;
252     WTErr err = _audio_device_manager.GetDeviceInfoByName(device_name, devInfo);
253     
254         if (eNoErr != err) {
255         std::cerr << "WavesAudioBackend::available_input_channel_count (): Failed to find device [" << device_name << "]" << std::endl;
256         return 0;
257     }
258
259     uint32_t num_of_input_channels = devInfo.m_MaxInputChannels;
260
261     // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::available_input_channel_count (): " << num_of_input_channels << std::endl;
262     return num_of_input_channels;
263 }
264
265
266 uint32_t 
267 WavesAudioBackend::available_output_channel_count (const std::string& device_name) const
268 {
269     DeviceInfo devInfo;
270     WTErr err = _audio_device_manager.GetDeviceInfoByName(device_name, devInfo);
271     
272         if (eNoErr != err) {
273         std::cerr << "WavesAudioBackend::available_output_channel_count (): Failed to find device [" << device_name << "]" << std::endl;
274         return 0;
275     }
276
277     uint32_t num_of_output_channels = devInfo.m_MaxOutputChannels;
278
279     // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::available_output_channel_count (): " << num_of_output_channels << std::endl;
280
281     return num_of_output_channels;
282 }
283
284
285 bool
286 WavesAudioBackend::can_change_sample_rate_when_running () const
287 {
288     // VERIFY IT CAREFULLY
289     return true;
290 }
291
292
293 bool
294 WavesAudioBackend::can_change_buffer_size_when_running () const
295 {
296     // VERIFY IT CAREFULLY
297     return true;
298 }
299
300
301 int
302 WavesAudioBackend::set_device_name (const std::string& device_name)
303 {
304     // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::set_device_name (): " << device_name << std::endl;
305     
306     if (_ports.size ()) {
307         std::cerr << "WavesAudioBackend::set_device_name (): There are unregistered ports left after [" << (_device ? _device->DeviceName () : std::string ("<NULL>")) << "]!" << std::endl;
308         for (size_t i = 0; i < _ports.size (); ++i) {
309             std::cerr << "\t[" << _ports[i]->name () << "]!" << std::endl;
310         }
311         return -1;
312     }
313
314         if (_device && _device->Streaming () ) {
315                 std::cerr << "WavesAudioBackend::set_device_name (): [" << _device->DeviceName () << "] is streaming! Current device must be stopped before setting another device as current" << std::endl;
316         }
317
318         // we must have only one device initialized at a time
319         // stop current device first
320         WTErr retVal;
321     if (_device) {
322         retVal = _device->SetActive (false);
323         if (retVal != eNoErr) {
324             std::cerr << "WavesAudioBackend::set_device_name (): [" << _device->DeviceName () << "]->SetActive (false) failed!" << std::endl;
325             return -1;
326         }
327     }
328
329         // deinitialize it
330         _audio_device_manager.DestroyCurrentDevice();
331         _device = 0;
332
333     WCMRAudioDevice * device = _audio_device_manager.InitNewCurrentDevice(device_name);
334
335     if (!device) {
336         std::cerr << "WavesAudioBackend::set_device_name (): Failed to initialize device [" << device_name << "]!" << std::endl;
337         return -1;
338     }
339
340
341     retVal = device->SetActive (true);
342     if (retVal != eNoErr) {
343         std::cerr << "WavesAudioBackend::set_device_name (): [" << device->DeviceName () << "]->SetActive () failed!" << std::endl;
344         return -1;
345     }
346
347     _device = device;
348     return 0;
349 }
350
351
352 int
353 WavesAudioBackend::drop_device()
354 {
355         WTErr wtErr = 0;
356
357         if (_device)
358         {
359                 wtErr = _device->SetActive (false);
360                 if (wtErr != eNoErr) {
361                         std::cerr << "WavesAudioBackend::drop_device (): [" << _device->DeviceName () << "]->SetActive () failed!" << std::endl;
362                         return -1;
363                 }
364         }
365
366         _audio_device_manager.DestroyCurrentDevice();
367         _device = 0;
368
369         return 0;
370 }
371
372
373 int 
374 WavesAudioBackend::set_sample_rate (float sample_rate)
375 {
376     // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::set_sample_rate (): " << sample_rate << std::endl;
377     
378     WTErr retVal = eNoErr;
379
380     if (!_device) {
381         std::cerr << "WavesAudioBackend::set_sample_rate (): No device is set!" << std::endl;
382         return -1;
383     }
384
385     
386     bool device_needs_restart = _device->Streaming ();
387     
388     if (device_needs_restart) {
389         retVal  = _device->SetStreaming (false);
390         // COMMENTED DBG LOGS */ std::cout << "\t\t[" << _device->DeviceName() << "]->_device->SetStreaming (false);"<< std::endl;
391         if (retVal != eNoErr) {
392             std::cerr << "WavesAudioBackend::set_sample_rate (): [" << _device->DeviceName () << "]->SetStreaming (false) failed (" << retVal << ") !" << std::endl;
393             return -1;
394         }
395     }
396     
397     retVal = _device->SetCurrentSamplingRate ((int)sample_rate);
398     
399     if (retVal != eNoErr) {
400         std::cerr << "WavesAudioBackend::set_sample_rate (): [" << _device->DeviceName() << "]->SetCurrentSamplingRate ((int)" << sample_rate << ") failed (" << retVal << ") !" << std::endl;
401         return -1;
402     }
403
404         _sample_rate_change(sample_rate);
405        
406     if (device_needs_restart) {
407         // COMMENTED DBG LOGS */ std::cout << "\t\t[" << _device->DeviceName() << "]->SetStreaming (true);"<< std::endl;
408         _call_thread_init_callback = true;
409         retVal  = _device->SetStreaming (true);
410         if (retVal != eNoErr) {
411             std::cerr << "WavesAudioBackend::set_sample_rate (): [" << _device->DeviceName () << "]->SetStreaming (true) failed (" << retVal << ") !" << std::endl;
412             return -1;
413         }
414     }
415     return 0;
416 }
417
418
419 int 
420 WavesAudioBackend::set_buffer_size (uint32_t buffer_size)
421 {
422     // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::set_buffer_size (" << buffer_size << "):"<< std::endl;
423
424     WTErr retVal = eNoErr;
425
426     if (!_device) {
427         std::cerr << "WavesAudioBackend::set_buffer_size (): No device is set!" << std::endl;
428         return -1;
429     }
430
431     bool device_needs_restart = _device->Streaming ();
432     
433     if (device_needs_restart) {
434         retVal  = _device->SetStreaming (false);
435         // COMMENTED DBG LOGS */ std::cout << "\t\t[" << _device->DeviceName() << "]->SetStreaming (false);"<< std::endl;
436         if (retVal != eNoErr) {
437             std::cerr << "WavesAudioBackend::set_buffer_size (): [" << _device->DeviceName () << "]->SetStreaming (false) failed (" << retVal << ") !" << std::endl;
438             return -1;
439         }
440     }
441     
442     retVal = _device->SetCurrentBufferSize (buffer_size);
443     
444     if (retVal != eNoErr) {
445         std::cerr << "WavesAudioBackend::set_buffer_size (): [" << _device->DeviceName() << "]->SetCurrentBufferSize (" << buffer_size << ") failed (" << retVal << ") !" << std::endl;
446         return -1;
447     }
448     
449         // if call to set buffer is successful but device buffer size differs from the value we tried to set
450         // this means we are driven by device for buffer size
451         buffer_size = _device->CurrentBufferSize ();
452
453         _buffer_size_change(buffer_size);
454     
455     if (device_needs_restart) {
456         // COMMENTED DBG LOGS */ std::cout << "\t\t[" << _device->DeviceName() << "]->SetStreaming (true);"<< std::endl;
457         _call_thread_init_callback = true;
458         retVal  = _device->SetStreaming (true);
459         if (retVal != eNoErr) {
460             std::cerr << "WavesAudioBackend::set_buffer_size (): [" << _device->DeviceName () << "]->SetStreaming (true) failed (" << retVal << ") !" << std::endl;
461             return -1;
462         }
463     }
464     
465     return 0;
466 }
467
468
469 int 
470 WavesAudioBackend::set_sample_format (SampleFormat sample_format)
471 {
472     // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::set_sample_format (): " << sample_format << std::endl;
473
474     _sample_format = sample_format;
475     return 0;
476 }
477
478 int 
479 WavesAudioBackend::reset_device ()
480 {
481     // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::_reset_device ():" << std::endl;
482
483     WTErr retVal = eNoErr;
484
485     if (!_device) {
486         std::cerr << "WavesAudioBackend::set_buffer_size (): No device is set!" << std::endl;
487         return -1;
488     }
489
490         return _device->ResetDevice();
491 }
492
493
494 int 
495 WavesAudioBackend::_buffer_size_change (uint32_t new_buffer_size)
496 {
497         _buffer_size = new_buffer_size;
498     _init_dsp_load_history();
499     return engine.buffer_size_change (new_buffer_size);
500 }
501
502
503 int 
504 WavesAudioBackend::_sample_rate_change (float new_sample_rate)
505 {
506         _sample_rate = new_sample_rate;
507     _init_dsp_load_history();
508     return engine.sample_rate_change (new_sample_rate);
509 }
510
511
512 int 
513 WavesAudioBackend::set_interleaved (bool yn)
514 {
515     /*you can ignore them totally*/
516     _interleaved = yn;
517     return 0;
518 }
519
520
521 int 
522 WavesAudioBackend::set_input_channels (uint32_t input_channels)
523 {
524     // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::set_input_channels (): " << input_channels << std::endl;
525
526     _input_channels = input_channels;
527     return 0;
528 }
529
530
531 int 
532 WavesAudioBackend::set_output_channels (uint32_t output_channels)
533 {
534     // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::set_output_channels (): " << output_channels << std::endl;
535
536     _output_channels = output_channels;
537     return 0;
538 }
539
540
541 std::string  
542 WavesAudioBackend::device_name () const
543 {
544     if (!_device) {
545         return "";
546     }
547     // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::device_name (): " << _device->DeviceName () << std::endl;
548     
549     return _device->DeviceName ();
550 }
551
552
553 float        
554 WavesAudioBackend::sample_rate () const
555 {
556     // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::sample_rate (): " << std::endl;
557
558     if (!_device) {
559         std::cerr << "WavesAudioBackend::sample_rate (): No device is set!" << std::endl;
560         return -1;
561     }
562
563     int sample_rate = _device->CurrentSamplingRate ();
564
565     // COMMENTED DBG LOGS */ std::cout << "\t[" << _device->DeviceName () << "]->CurrentSamplingRate () returned " << sample_rate << std::endl;
566
567     return (float)sample_rate;
568 }
569
570
571 uint32_t     
572 WavesAudioBackend::buffer_size () const
573 {
574
575     // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::buffer_size (): " << std::endl;
576
577     if (!_device) {
578         std::cerr << "WavesAudioBackend::buffer_size (): No device is set!" << std::endl;
579         return 0;
580     }
581
582     int size = _device->CurrentBufferSize ();
583     
584     // COMMENTED DBG LOGS */ std::cout << "\t[" << _device->DeviceName () << "]->CurrentBufferSize () returned " << size << std::endl;
585
586     return (uint32_t)size;
587 }
588
589
590 SampleFormat 
591 WavesAudioBackend::sample_format () const
592 {
593     // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::sample_format ()" << std::endl;
594     return _sample_format;
595 }
596
597
598 bool         
599 WavesAudioBackend::interleaved () const
600 {
601     // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::interleaved ()" << std::endl;
602
603     return _interleaved;
604 }
605
606
607 uint32_t     
608 WavesAudioBackend::input_channels () const
609 {
610     // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::input_channels ()" << std::endl;
611
612     return _input_channels;
613 }
614
615
616 uint32_t     
617 WavesAudioBackend::output_channels () const
618 {
619     // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::output_channels ()" << std::endl;
620
621     return _output_channels;
622 }
623
624
625 std::string 
626 WavesAudioBackend::control_app_name () const
627 {
628     std::string app_name = ""; 
629
630     if (_device && !dynamic_cast<WCMRNativeAudioNoneDevice*> (_device))    {
631         app_name = "PortAudioMayKnowIt";
632     }
633
634     return app_name; 
635 }
636
637
638 void
639 WavesAudioBackend::launch_control_app ()
640 {
641     // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::launch_control_app ()" << std::endl;
642     if (!_device) {
643         std::cerr << "WavesAudioBackend::launch_control_app (): No device is set!" << std::endl;
644         return;
645     }
646     
647     WTErr err = _device->ShowConfigPanel (NULL);
648     
649     if (eNoErr != err) {
650         std::cerr << "WavesAudioBackend::launch_control_app (): [" << _device->DeviceName () << "]->ShowConfigPanel () failed (" << err << ")!" << std::endl;
651     }
652
653     // COMMENTED DBG LOGS */ else std::cout << "WavesAudioBackend::launch_control_app (): [" << _device->DeviceName () << "]->ShowConfigPanel ()  successfully launched!" << std::endl;
654 }
655
656
657 int
658 WavesAudioBackend::_start (bool for_latency_measurement)
659 {
660     // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::_start ()" << std::endl;
661
662     if (!_device) {
663         std::cerr << "WavesAudioBackend::_start (): No device is set!" << std::endl;
664         stop();
665                 return -1;
666     }
667
668     if (_register_system_audio_ports () != 0) {
669         std::cerr << "WavesAudioBackend::_start (): _register_system_audio_ports () failed!" << std::endl;
670         stop();
671                 return -1;
672     }
673
674     if (_use_midi) {
675         if (_midi_device_manager.start () != 0) {
676             std::cerr << "WavesAudioBackend::_start (): _midi_device_manager.start () failed!" << std::endl;
677             stop();
678                         return -1;
679         }
680         if (_register_system_midi_ports () != 0) {
681             std::cerr << "WavesAudioBackend::_start (): _register_system_midi_ports () failed!" << std::endl;
682             stop();
683                         return -1;
684         }
685     }
686
687     if (engine.reestablish_ports () != 0) {
688         std::cerr << "WavesAudioBackend::_start (): engine.reestablish_ports () failed!" << std::endl;
689     }
690
691     manager.registration_callback ();
692
693     _call_thread_init_callback = true;
694     WTErr retVal  = _device->SetStreaming (true);
695     if (retVal != eNoErr) {
696         std::cerr << "WavesAudioBackend::_start (): [" << _device->DeviceName () << "]->SetStreaming () failed!" << std::endl;
697                 stop();
698         return -1;
699     }
700
701     if (_use_midi) {
702         if (_midi_device_manager.stream (true)) {
703             std::cerr << "WavesAudioBackend::_start (): _midi_device_manager.stream (true) failed!" << std::endl;
704             stop();
705                         return -1;
706         }
707     }
708
709     return 0;
710 }
711
712
713 void
714 WavesAudioBackend::_audio_device_callback (const float* input_buffer, 
715                                            float* output_buffer, 
716                                            unsigned long nframes,
717                                            pframes_t sample_time,
718                                            uint64_t cycle_start_time_nanos)
719 {
720     uint64_t dsp_start_time_nanos = __get_time_nanos();
721     // COMMENTED FREQUENT DBG LOGS */ std::cout << "WavesAudioBackend::_audio_device_callback ():" << _device->DeviceName () << std::endl;
722     _sample_time_at_cycle_start = sample_time;
723     _cycle_start_time_nanos = cycle_start_time_nanos;
724     
725     /* There is the possibility that the thread this runs in may change from
726      *  callback to callback, so do it every time.
727      */
728     _main_thread = pthread_self ();
729
730     if (_buffer_size != nframes) {
731         // COMMENTED DBG LOGS */ std::cout << "\tAudioEngine::thread_init_callback() buffer size and nframes are not equal: " << _buffer_size << "!=" << nframes << std::endl;
732         return;
733     }
734
735     _read_audio_data_from_device (input_buffer, nframes);
736     _read_midi_data_from_devices ();
737
738     if (_call_thread_init_callback) {
739         _call_thread_init_callback = false;
740         // COMMENTED DBG LOGS */ std::cout << "\tAudioEngine::thread_init_callback() invoked for " << std::hex << pthread_self() << std::dec << " !" << std::endl;
741         AudioEngine::thread_init_callback (this);
742     }
743
744     engine.process_callback (nframes);
745     
746     _write_audio_data_to_device (output_buffer, nframes);
747     _write_midi_data_to_devices (nframes);
748     
749     uint64_t dsp_end_time_nanos = __get_time_nanos();
750     
751     _dsp_load_accumulator -= *_dsp_load_history.begin();
752         _dsp_load_history.pop_front();
753     uint64_t dsp_load_nanos = dsp_end_time_nanos - dsp_start_time_nanos;
754     _dsp_load_accumulator += dsp_load_nanos;
755     _dsp_load_history.push_back(dsp_load_nanos);
756
757     return;
758 }
759
760
761 int
762 WavesAudioBackend::stop ()
763 {
764     // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::stop ()" << std::endl;
765
766     WTErr wtErr = eNoErr;
767     int retVal = 0;
768
769     // COMMENTED DBG LOGS */ std::cout << "\t[" << _device->DeviceName () << "]" << std::endl;
770
771         if (_device) {
772                 wtErr = _device->SetStreaming (false);
773                 if (wtErr != eNoErr) {
774                         std::cerr << "WavesAudioBackend::stop (): [" << _device->DeviceName () << "]->SetStreaming () failed!" << std::endl;
775                         retVal = -1;
776                 }
777         }
778
779     _midi_device_manager.stop ();
780
781     _unregister_system_audio_ports ();
782     _unregister_system_midi_ports ();
783
784     return retVal;
785 }
786
787
788 int
789 WavesAudioBackend::freewheel (bool start_stop)
790 {
791     // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::freewheel (" << start_stop << "):" << std::endl;
792
793     if (start_stop != _freewheeling) {
794         if (start_stop == true) {
795             WTErr retval = _device->SetStreaming (false);
796             if (retval != eNoErr) {
797                 std::cerr << "WavesAudioBackend::freewheel (): [" << _device->DeviceName () << "]->SetStreaming () failed!" << std::endl;
798                 return -1;
799             }
800             _call_thread_init_callback = true;
801             _freewheel_thread ();
802             engine.freewheel_callback (start_stop);
803         }
804         else {
805             _freewheel_thread_active = false; // stop _freewheel_thread ()
806             engine.freewheel_callback (start_stop);
807             _call_thread_init_callback = true;
808             WTErr retval = _device->SetStreaming (true);
809             if (retval != eNoErr) {
810                 std::cerr << "WavesAudioBackend::freewheel (): [" << _device->DeviceName () << "]->SetStreaming () failed!" << std::endl;
811                 return -1;
812             }
813         }
814         _freewheeling = start_stop;
815     }
816     // already doing what has been asked for
817     return 0;
818 }
819
820
821 void 
822 WavesAudioBackend::_freewheel_thread ()
823 {
824     // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::_freewheel_thread ():" << std::endl;
825     if (!_freewheel_thread_active) { // Lets create it
826         
827         // COMMENTED DBG LOGS */ std::cout << "\tCreating the thread _freewheel_thread () . . ." << std::endl;
828         pthread_attr_t attributes;
829         pthread_t thread_id;
830
831         ThreadData* thread_data = new ThreadData (this, boost::bind (&WavesAudioBackend::_freewheel_thread, this), __thread_stack_size ());
832
833         if (pthread_attr_init (&attributes)) {
834             std::cerr << "WavesAudioBackend::freewheel_thread (): pthread_attr_init () failed!" << std::endl;
835             return;
836         }
837    
838         if (pthread_attr_setstacksize (&attributes, __thread_stack_size ())) {
839             std::cerr << "WavesAudioBackend::freewheel_thread (): pthread_attr_setstacksize () failed!" << std::endl;
840             return;
841         }
842
843         _freewheel_thread_active = false;
844         if ((pthread_create (&thread_id, &attributes, __start_process_thread, thread_data))) {
845             _freewheel_thread_active = true;
846             std::cerr << "WavesAudioBackend::freewheel_thread (): pthread_create () failed!" << std::endl;
847             return;
848         }
849
850         // COMMENTED DBG LOGS */ std::cout << "\t. . . _freewheel_thread () complete." << std::endl;
851         return;
852     }
853     
854     if (_call_thread_init_callback) {
855         _call_thread_init_callback = false;
856         AudioEngine::thread_init_callback (this);
857     }
858
859     while (_freewheel_thread_active) {
860         engine.process_callback (_buffer_size);
861     }
862     // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::_freewheel_thread (): FINISHED" << std::endl;
863     return;
864 }
865
866
867 float
868 WavesAudioBackend::dsp_load () const
869 {
870     // COMMENTED FREQUENT DBG LOGS */ std::cout << "WavesAudioBackend::dsp_load (): " << std::endl;
871
872     if (!_device) {
873         std::cerr << "WavesAudioBackend::cpu_load (): No device is set!" << std::endl;
874         return 0;
875     }
876
877     float average_dsp_load = (float)_dsp_load_accumulator/_dsp_load_history_length;
878     
879     return ( average_dsp_load  / _audio_cycle_period_nanos)*100.0;
880 }
881
882
883 void
884 WavesAudioBackend::_init_dsp_load_history()
885 {
886     if((_sample_rate <= 0.0) || (_buffer_size <= 0.0)) {
887         return;
888     }
889     
890     _audio_cycle_period_nanos = ((uint64_t)1000000000L * _buffer_size) / _sample_rate;
891     
892     _dsp_load_accumulator = 0;
893     
894     _dsp_load_history_length = (_sample_rate + _buffer_size - 1) / _buffer_size;
895     // COMMENTED DBG LOGS */ std::cout << "\t\t_dsp_load_history_length = " << _dsp_load_history_length << std::endl;
896     _dsp_load_history = std::list<uint64_t>(_dsp_load_history_length, 0);
897 }
898
899
900 void
901 WavesAudioBackend::transport_start ()
902 {
903     // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::transport_start (): " << std::endl;
904 }
905
906
907 void
908 WavesAudioBackend::transport_stop () 
909 {
910     // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::transport_stop (): " << std::endl;
911 }
912
913
914 TransportState
915 WavesAudioBackend::transport_state () const
916 {
917     // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::transport_state (): " << std::endl;
918     return TransportStopped; 
919 }
920
921
922 void
923 WavesAudioBackend::transport_locate (framepos_t pos)
924 {
925     // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::transport_locate (" << pos << "): " << std::endl;
926 }
927
928
929 framepos_t
930 WavesAudioBackend::transport_frame () const
931
932     // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::transport_frame (): " << std::endl;
933     return 0; 
934 }
935
936
937 int
938 WavesAudioBackend::set_time_master (bool yn)
939
940     // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::set_time_master (): " << yn << std::endl;
941     return 0; 
942 }
943
944
945 int
946 WavesAudioBackend::usecs_per_cycle () const
947 {
948     // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::usecs_per_cycle (): " << std::endl;
949     return (1000000 * _sample_rate) / _buffer_size;
950 }
951
952
953 size_t
954 WavesAudioBackend::raw_buffer_size (DataType data_type)
955 {
956     // COMMENTED FREQUENT DBG LOGS */ std::cout << "WavesAudioBackend::raw_buffer_size (" << data_type.to_string () << "): " << std::endl;
957     switch (data_type) {
958     case DataType::AUDIO:
959             return WavesAudioPort::MAX_BUFFER_SIZE_BYTES;
960         break;
961
962     case DataType::MIDI:
963             return WavesMidiPort::MAX_BUFFER_SIZE_BYTES;
964         break;
965
966         default:
967             std::cerr << "WavesAudioBackend::raw_buffer_size (): unexpected data type (" << (uint32_t)data_type <<")!" << std::endl;
968         break;
969     }
970     return 0;
971 }
972
973
974 pframes_t
975 WavesAudioBackend::sample_time ()
976 {
977     // WARNING: This is approximate calculation. Implementation of accurate calculation is pending.
978     // http://kokkinizita.linuxaudio.org/papers/usingdll.pdf
979     
980     return _sample_time_at_cycle_start + ((__get_time_nanos () - _cycle_start_time_nanos)*_sample_rate)/1000000000L;
981 }
982
983
984 uint64_t
985 WavesAudioBackend::__get_time_nanos ()
986 {
987 #ifdef __APPLE__
988     // here we exploit the time counting API which is used by the WCMRCoreAudioDeviceManager. However,
989     // the API should be a part of WCMRCoreAudioDeviceManager to give a chance of being tied to the
990     // audio device transport timeß.
991     return AudioConvertHostTimeToNanos (AudioGetCurrentHostTime ());
992     
993 #elif PLATFORM_WINDOWS
994         LARGE_INTEGER Count;
995     QueryPerformanceCounter (&Count);
996     return uint64_t ((Count.QuadPart * 1000000000L / __performance_counter_frequency));
997 #endif
998 }
999
1000
1001 pframes_t
1002 WavesAudioBackend::sample_time_at_cycle_start ()
1003 {
1004     // COMMENTED FREQUENT DBG LOGS */ std::cout << "WavesAudioBackend::sample_time_at_cycle_start (): " << _sample_time_at_cycle_start << std::endl;
1005     return _sample_time_at_cycle_start;
1006 }
1007
1008
1009 pframes_t
1010 WavesAudioBackend::samples_since_cycle_start ()
1011 {
1012     pframes_t diff_sample_time; 
1013     diff_sample_time = sample_time () - _sample_time_at_cycle_start;
1014     // COMMENTED DBG LOGS */ std::cout << "samples_since_cycle_start: " << diff_sample_time << std::endl;
1015
1016     return diff_sample_time;
1017 }
1018
1019
1020 bool
1021 WavesAudioBackend::get_sync_offset (pframes_t& /*offset*/) const
1022
1023     // COMMENTED DBG LOGS */ std::cout << "get_sync_offset: false" << std::endl;
1024
1025     return false; 
1026 }
1027
1028
1029 int
1030 WavesAudioBackend::create_process_thread (boost::function<void ()> func)
1031 {
1032     // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::create_process_thread ():" << std::endl;
1033     int retVal;
1034     pthread_attr_t attributes;
1035     size_t stacksize_aligned;
1036     pthread_t thread_id;
1037
1038     // Align stacksize to PTHREAD_STACK_MIN.
1039     stacksize_aligned = __thread_stack_size ();
1040
1041     ThreadData* td = new ThreadData (this, func, stacksize_aligned);
1042
1043     if ((retVal = pthread_attr_init (&attributes))) {
1044         std::cerr << "Cannot set thread attr init res = " << retVal << endmsg;
1045         return -1;
1046     }
1047    
1048     if ((retVal = pthread_attr_setstacksize (&attributes, stacksize_aligned))) {
1049         std::cerr << "Cannot set thread stack size (" << stacksize_aligned << ") res = " << retVal << endmsg;
1050         return -1;
1051     }
1052
1053     if ((retVal = pthread_create (&thread_id, &attributes, __start_process_thread, td))) {
1054         std::cerr << "Cannot create thread res = " << retVal << endmsg;
1055         return -1;
1056     }
1057
1058     _backend_threads.push_back (thread_id);
1059     // COMMENTED DBG LOGS */ std::cout << "\t\t\t. . . thread " << std::hex << thread_id << std::dec << " has been created" << std::endl;
1060
1061     return 0;
1062 }
1063
1064
1065 void*
1066 WavesAudioBackend::__start_process_thread (void* arg)
1067 {
1068     // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::__start_process_thread ():" << std::endl;
1069     ThreadData* td = reinterpret_cast<ThreadData*> (arg);
1070     boost::function<void ()> f = td->f;
1071     delete td;
1072     f ();
1073     return 0;
1074 }
1075
1076
1077 int
1078 WavesAudioBackend::join_process_threads ()
1079 {
1080     // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::join_process_thread ()" << std::endl;
1081     int ret = 0;
1082
1083     for (std::vector<pthread_t>::const_iterator i = _backend_threads.begin ();
1084          i != _backend_threads.end ();
1085          ++i) {
1086         // COMMENTED DBG LOGS */ std::cout << "\t\t\tstopping thread " << std::hex << *i << std::dec << "...\n";
1087
1088         void* status;  
1089         if (pthread_join (*i, &status) != 0) {
1090             std::cerr << "AudioEngine: cannot stop process thread !" << std::endl;
1091             ret += -1;
1092         }
1093         // COMMENTED DBG LOGS */ std::cout << "\t\t\t\t...done" << std::endl;
1094     }
1095     // COMMENTED DBG LOGS */ std::cout << "\t\t\tall threads finished..." << std::endl;
1096     _backend_threads.clear ();
1097     // COMMENTED DBG LOGS */ std::cout << "\t\t\tthread list cleared..." << std::endl;
1098
1099     return ret;
1100 }
1101
1102
1103 bool 
1104 WavesAudioBackend::in_process_thread ()
1105 {
1106     // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::in_process_thread ()" << std::endl;
1107         if (pthread_equal (_main_thread, pthread_self()) != 0) {
1108                 return true;
1109         }
1110         for (std::vector<pthread_t>::const_iterator i = _backend_threads.begin ();
1111              i != _backend_threads.end (); i++) {
1112                 if (pthread_equal (*i, pthread_self ()) != 0) {
1113                         return true;
1114                 }
1115         }
1116         return false;
1117 }
1118
1119
1120 size_t
1121 WavesAudioBackend::__thread_stack_size ()
1122 {
1123     // Align stacksize to PTHREAD_STACK_MIN.
1124 #if defined (__APPLE__)
1125     return (((thread_stack_size () - 1) / PTHREAD_STACK_MIN) + 1) * PTHREAD_STACK_MIN;
1126 #elif defined (PLATFORM_WINDOWS)
1127     return thread_stack_size ();
1128 #endif
1129 }
1130
1131
1132 uint32_t 
1133 WavesAudioBackend::process_thread_count ()
1134 {
1135     // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::process_thread_count (): returns " << _backend_threads.size () << std::endl;
1136     return _backend_threads.size ();
1137 }
1138
1139
1140 void
1141 WavesAudioBackend::_read_audio_data_from_device (const float* input_buffer, pframes_t nframes)
1142 {
1143 #if defined(PLATFORM_WINDOWS)
1144     const float **buffer = (const float**)input_buffer;
1145     size_t copied_bytes = nframes*sizeof(float);
1146
1147     for(std::vector<WavesAudioPort*>::iterator it = _physical_audio_inputs.begin ();
1148         it != _physical_audio_inputs.end();
1149         ++it)
1150     {
1151         memcpy((*it)->buffer(), *buffer, copied_bytes);
1152         ++buffer;
1153     }
1154 #else
1155     std::vector<WavesAudioPort*>::iterator it = _physical_audio_inputs.begin ();
1156
1157     // Well, let's de-interleave here:
1158     const Sample* source = input_buffer;
1159
1160     for (uint32_t chann_cnt = 0; (chann_cnt < _max_input_channels) && (it != _physical_audio_inputs.end ()); ++chann_cnt, ++source, ++it) {
1161         const Sample* src = source;
1162         Sample* tgt = (*it)->buffer ();
1163
1164         for (uint32_t frame = 0; frame < nframes; ++frame, src += _max_input_channels, ++tgt) {
1165             *tgt = *src;
1166         }
1167     }
1168 #endif
1169 }
1170
1171 void
1172 WavesAudioBackend::_write_audio_data_to_device (float* output_buffer, pframes_t nframes)
1173 {
1174 #if defined(_WnonononoINDOWS)
1175     float **buffer = (float**)output_buffer;
1176     size_t copied_bytes = nframes*sizeof(float);
1177     int i = 0;
1178     for(std::vector<WavesAudioPort*>::iterator it = _physical_audio_outputs.begin ();
1179         it != _physical_audio_outputs.end();
1180         ++it)
1181     {
1182         memcpy(*buffer, (*it)->buffer(), copied_bytes);
1183         //*buffer = (*it)->buffer();
1184         buffer++;
1185     }
1186 #else
1187     // Well, let's interleave here:
1188     std::vector<WavesAudioPort*>::iterator it = _physical_audio_outputs.begin ();
1189     Sample* target = output_buffer;
1190
1191     for (uint32_t chann_cnt = 0;
1192          (chann_cnt < _max_output_channels) && (it != _physical_audio_outputs.end ());
1193          ++chann_cnt, ++target, ++it) {
1194         const Sample* src = (Sample*) ((*it)->get_buffer (nframes));
1195         Sample* tgt = target;
1196         for (uint32_t frame = 0; frame < nframes; ++frame, tgt += _max_output_channels, ++src) {
1197             *tgt = *src;
1198         }
1199     }
1200 #endif
1201 }
1202
1203
1204 static boost::shared_ptr<WavesAudioBackend> __instance;
1205
1206
1207 boost::shared_ptr<AudioBackend>
1208 WavesAudioBackend::__waves_backend_factory (AudioEngine& e)
1209 {
1210     // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::__waves_backend_factory ():" << std::endl;
1211     if (!__instance) {
1212             __instance.reset (new WavesAudioBackend (e));
1213     }
1214     return __instance;
1215 }
1216
1217
1218 #if defined(PLATFORM_WINDOWS)
1219
1220 uint64_t WavesAudioBackend::__performance_counter_frequency;
1221
1222 #endif
1223
1224 int 
1225 WavesAudioBackend::__instantiate (const std::string& arg1, const std::string& arg2)
1226 {
1227     // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::__instantiate ():" << "[" << arg1 << "], [" << arg2 << "]" << std::endl;
1228     __instantiated_name = arg1;
1229 #if defined(PLATFORM_WINDOWS)
1230
1231         LARGE_INTEGER Frequency;
1232         QueryPerformanceFrequency(&Frequency);
1233         __performance_counter_frequency = Frequency.QuadPart;
1234         std::cout << "__performance_counter_frequency:" << __performance_counter_frequency << std::endl;
1235
1236 #endif
1237     return 0;
1238 }
1239
1240
1241 int 
1242 WavesAudioBackend::__deinstantiate ()
1243 {
1244     // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::__deinstantiate ():" << std::endl;
1245     __instance.reset ();
1246     return 0;
1247 }
1248
1249
1250 bool
1251 WavesAudioBackend::__already_configured ()
1252 {
1253     // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::__already_configured ():" << std::endl;
1254     return false;
1255 }
1256
1257
1258 void*
1259 WavesAudioBackend::private_handle () const
1260 {
1261     // COMMENTED DBG LOGS */ std::cout << "WHY DO CALL IT: WavesAudioBackend::private_handle: " << std::endl;
1262     return NULL;
1263 }
1264
1265
1266 bool
1267 WavesAudioBackend::available () const
1268 {
1269     // COMMENTED SECONDARY DBG LOGS */// std::cout << "WavesAudioBackend::available: " << std::endl;
1270     return true;
1271 }
1272
1273
1274 const std::string&
1275 WavesAudioBackend::my_name () const
1276 {
1277     // COMMENTED SECONDARY DBG LOGS */// std::cout << "WavesAudioBackend::my_name: " << _port_prefix_name << std::endl;
1278     return __instantiated_name;
1279 }
1280
1281
1282 bool
1283 WavesAudioBackend::can_monitor_input () const
1284 {
1285     // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::can_monitor_input: " << std::endl;
1286     return false;
1287 }
1288
1289 std::string WavesAudioBackend::__instantiated_name;
1290
1291 AudioBackendInfo WavesAudioBackend::__backend_info = {
1292 #ifdef __APPLE__
1293     "CoreAudio",
1294 #elif PLATFORM_WINDOWS
1295     "ASIO",
1296 #endif
1297     __instantiate,
1298     WavesAudioBackend::__deinstantiate,
1299     WavesAudioBackend::__waves_backend_factory,
1300     WavesAudioBackend::__already_configured,
1301 };
1302
1303