1 /***************************************************************************
2  *                                                                         *
3  *   LinuxSampler - modular, streaming capable sampler                     *
4  *                                                                         *
5  *   Copyright (C) 2009 Grigor Iliev                                       *
6  *   Copyright (C) 2011-2013 Andreas Persson                               *
7  *   Copyright (C) 2014-2020 Christian Schoenebeck                         *
8  *                                                                         *
9  *   This program is free software; you can redistribute it and/or modify  *
10  *   it under the terms of the GNU General Public License as published by  *
11  *   the Free Software Foundation; either version 2 of the License, or     *
12  *   (at your option) any later version.                                   *
13  *                                                                         *
14  *   This program is distributed in the hope that it will be useful,       *
15  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
16  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
17  *   GNU General Public License for more details.                          *
18  *                                                                         *
19  *   You should have received a copy of the GNU General Public License     *
20  *   along with this program; if not, write to the Free Software           *
21  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston,                 *
22  *   MA  02111-1307  USA                                                   *
23  ***************************************************************************/
24 
25 #include "AudioOutputDeviceCoreAudio.h"
26 
27 #include "../../common/global_private.h"
28 
29 namespace LinuxSampler {
30 
AudioQueueListener(void * inUserData,AudioQueueRef inAQ,AudioQueuePropertyID inID)31     void AudioOutputDeviceCoreAudio::AudioQueueListener (
32             void *inUserData, AudioQueueRef inAQ, AudioQueuePropertyID inID
33     ) {
34         switch(inID) {
35             case kAudioQueueProperty_IsRunning:
36 
37                 break;
38             case kAudioQueueProperty_CurrentDevice:
39 
40                 break;
41         }
42     }
43 
HandleOutputBuffer(void * aqData,AudioQueueRef inAQ,AudioQueueBufferRef inBuffer)44     void AudioOutputDeviceCoreAudio::HandleOutputBuffer (
45         void                 *aqData,
46         AudioQueueRef        inAQ,
47         AudioQueueBufferRef  inBuffer
48     ) {
49         AQPlayerState* pAqData = (AQPlayerState*) aqData;
50         if (atomic_read(&(pAqData->mIsRunning)) == 0) {
51             AudioQueueFlush(pAqData->mQueue);
52             AudioQueueStop (pAqData->mQueue, true);
53             return;
54         }
55 
56         if(atomic_read(&(pAqData->pDevice->restartQueue))) return;
57 
58         uint bufferSize = pAqData->pDevice->uiBufferSize;
59 
60         // let all connected engines render 'fragmentSize' sample points
61         pAqData->pDevice->RenderAudio(bufferSize);
62 
63         Float32* pDataBuf = (Float32*)(inBuffer->mAudioData);
64 
65         uint uiCoreAudioChannels = pAqData->pDevice->uiCoreAudioChannels;
66         for (int c = 0; c < uiCoreAudioChannels; c++) {
67             float* in  = pAqData->pDevice->Channels[c]->Buffer();
68             for (int i = 0, o = c; i < bufferSize; i++ , o += uiCoreAudioChannels) {
69                 pDataBuf[o] = in[i];
70             }
71         }
72 
73         inBuffer->mAudioDataByteSize = (uiCoreAudioChannels * 4) * bufferSize;
74 
75         OSStatus res = AudioQueueEnqueueBuffer(pAqData->mQueue, inBuffer, 0, NULL);
76         if(res) std::cerr << "AudioQueueEnqueueBuffer: Error " << res << std::endl;
77     }
78 
DeviceChanged()79     void AudioOutputDeviceCoreAudio::DeviceChanged() {
80         dmsg(1,("Restarting audio queue..."));
81         atomic_set(&restartQueue, 1);
82     }
83 
AudioOutputDeviceCoreAudio(std::map<String,DeviceCreationParameter * > Parameters)84     AudioOutputDeviceCoreAudio::AudioOutputDeviceCoreAudio (
85                     std::map<String,DeviceCreationParameter*> Parameters
86     ) : AudioOutputDevice(Parameters), Thread(true, true, 1, 0), CurrentDevice(0) {
87 
88         dmsg(2,("AudioOutputDeviceCoreAudio::AudioOutputDeviceCoreAudio()\n"));
89         if(CAAudioDeviceListModel::GetModel()->GetOutputDeviceCount() < 1) {
90             throw Exception("No audio output device found");
91         }
92         atomic_set(&pausedNew, 0);
93         pausedOld = 0;
94         atomic_set(&restartQueue, 0);
95 
96         uiCoreAudioChannels = ((DeviceCreationParameterInt*)Parameters["CHANNELS"])->ValueAsInt();
97         uint samplerate     = ((DeviceCreationParameterInt*)Parameters["SAMPLERATE"])->ValueAsInt();
98         uiBufferNumber      = ((DeviceCreationParameterInt*)Parameters["BUFFERS"])->ValueAsInt();
99         uiBufferSize        = ((DeviceCreationParameterInt*)Parameters["BUFFERSIZE"])->ValueAsInt();
100         int device = 0;
101         try { device = ((ParameterDevice*)Parameters["DEVICE"])->GetDeviceIndex(); }
102         catch(Exception x) { }
103 
104         CurrentDevice = CAAudioDeviceListModel::GetModel()->GetOutputDevice(device);
105         CurrentDevice.AddListener(this);
106 
107         memset (&aqPlayerState.mDataFormat, 0, sizeof(AudioStreamBasicDescription));
108 
109         aqPlayerState.mDataFormat.mSampleRate = samplerate;
110         aqPlayerState.mDataFormat.mFormatID = kAudioFormatLinearPCM;
111 
112         aqPlayerState.mDataFormat.mFormatFlags =
113             kLinearPCMFormatFlagIsFloat | kLinearPCMFormatFlagIsPacked;
114 
115         int samplesize = 4;
116         aqPlayerState.mDataFormat.mBytesPerPacket = uiCoreAudioChannels * samplesize;
117         aqPlayerState.mDataFormat.mFramesPerPacket = 1;
118         aqPlayerState.mDataFormat.mBytesPerFrame = uiCoreAudioChannels * samplesize;
119         aqPlayerState.mDataFormat.mChannelsPerFrame = uiCoreAudioChannels;
120         aqPlayerState.mDataFormat.mBitsPerChannel = 8 * samplesize;
121         aqPlayerState.mDataFormat.mReserved = 0;
122 
123         aqPlayerState.mBuffers = new AudioQueueBufferRef[uiBufferNumber];
124 
125         aqPlayerState.bufferByteSize =
126                 MaxSamplesPerCycle() * aqPlayerState.mDataFormat.mBytesPerFrame;
127 
128         aqPlayerState.mNumPacketsToRead = MaxSamplesPerCycle();
129 
130         aqPlayerState.pDevice = this;
131         aqPlayerState.mQueue = NULL;
132 
133         uint fragmentSize = MaxSamplesPerCycle();
134         // create audio channels for this audio device to which the sampler engines can write to
135         for (int i = 0; i < uiCoreAudioChannels; i++) {
136             this->Channels.push_back(new AudioChannel(i, fragmentSize));
137         }
138 
139         StartThread();
140 
141         if (!((DeviceCreationParameterBool*)Parameters["ACTIVE"])->ValueAsBool()) {
142 		Stop();
143 	}
144     }
145 
~AudioOutputDeviceCoreAudio()146     AudioOutputDeviceCoreAudio::~AudioOutputDeviceCoreAudio() {
147         StopThread();
148 
149         atomic_set(&(aqPlayerState.mIsRunning), 0);
150         {
151             LockGuard lock(destroyMutex);
152             AudioQueueDispose(aqPlayerState.mQueue, true);
153         }
154         delete [] aqPlayerState.mBuffers;
155 
156         CurrentDevice.RemoveListener(this);
157     }
158 
Name()159     String AudioOutputDeviceCoreAudio::Name() {
160         return "COREAUDIO";
161     }
162 
Description()163     String AudioOutputDeviceCoreAudio::Description() {
164         return "Apple CoreAudio";
165     }
166 
Version()167     String AudioOutputDeviceCoreAudio::Version() {
168        String s = "$Revision: 3766 $";
169        return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword
170     }
171 
Play()172     void AudioOutputDeviceCoreAudio::Play() {
173         atomic_set(&pausedNew, 0);
174     }
175 
IsPlaying()176     bool AudioOutputDeviceCoreAudio::IsPlaying() {
177         return !atomic_read(&pausedNew);
178     }
179 
Stop()180     void AudioOutputDeviceCoreAudio::Stop() {
181         atomic_set(&pausedNew, 1);
182     }
183 
MaxSamplesPerCycle()184     uint AudioOutputDeviceCoreAudio::MaxSamplesPerCycle() {
185         return uiBufferSize;
186     }
187 
SampleRate()188     uint AudioOutputDeviceCoreAudio::SampleRate() {
189         return aqPlayerState.mDataFormat.mSampleRate;
190     }
191 
Driver()192     String AudioOutputDeviceCoreAudio::Driver() {
193         return Name();
194     }
195 
CreateChannel(uint ChannelNr)196     AudioChannel* AudioOutputDeviceCoreAudio::CreateChannel(uint ChannelNr) {
197         // just create a mix channel
198         return new AudioChannel(ChannelNr, Channel(ChannelNr % uiCoreAudioChannels));
199     }
200 
FillBuffers()201     void AudioOutputDeviceCoreAudio::FillBuffers() {
202         for (int i = 0; i < uiBufferNumber; ++i) {
203             HandleOutputBuffer (
204                 &aqPlayerState,
205                 aqPlayerState.mQueue,
206                 aqPlayerState.mBuffers[i]
207             );
208         }
209     }
210 
PrimeAudioQueue()211     void AudioOutputDeviceCoreAudio::PrimeAudioQueue() {
212         OSStatus res = AudioQueuePrime(aqPlayerState.mQueue, 0, NULL);
213         if(res) {
214             String s = String("AudioQueuePrime: Error ") + ToString(res);
215             throw Exception(s);
216         }
217     }
218 
CreateAndStartAudioQueue()219     void AudioOutputDeviceCoreAudio::CreateAndStartAudioQueue() throw(Exception) {
220         OSStatus res = AudioQueueNewOutput (
221             &aqPlayerState.mDataFormat,
222             HandleOutputBuffer,
223             &aqPlayerState,
224             CFRunLoopGetCurrent(),
225             kCFRunLoopCommonModes,
226             0,
227             &aqPlayerState.mQueue
228         );
229 
230         if(res) {
231             String s = String("AudioQueueNewOutput: Error ") + ToString(res);
232             throw Exception(s);
233         }
234 
235         CFStringRef devUID = CFStringCreateWithCString (
236             NULL, CurrentDevice.GetUID().c_str(), kCFStringEncodingASCII
237         );
238         res = AudioQueueSetProperty (
239             aqPlayerState.mQueue,
240             kAudioQueueProperty_CurrentDevice,
241             &devUID, sizeof(CFStringRef)
242         );
243         CFRelease(devUID);
244 
245         if(res) {
246             String s = String("Failed to set audio device: ") + ToString(res);
247             throw Exception(s);
248         }
249 
250         for (int i = 0; i < uiBufferNumber; ++i) {
251             res = AudioQueueAllocateBuffer (
252                 aqPlayerState.mQueue,
253                 aqPlayerState.bufferByteSize,
254                 &aqPlayerState.mBuffers[i]
255             );
256 
257             if(res) {
258                 String s = String("AudioQueueAllocateBuffer: Error ");
259                 throw Exception(s + ToString(res));
260             }
261         }
262 
263         res = AudioQueueAddPropertyListener (
264             aqPlayerState.mQueue,
265             kAudioQueueProperty_CurrentDevice,
266             AudioQueueListener,
267             NULL
268         );
269         if(res) std::cerr << "Failed to register device change listener: " << res << std::endl;
270 
271         res = AudioQueueAddPropertyListener (
272             aqPlayerState.mQueue,
273             kAudioQueueProperty_IsRunning,
274             AudioQueueListener,
275             NULL
276         );
277         if(res) std::cerr << "Failed to register running listener: " << res << std::endl;
278 
279         Float32 gain = 1.0;
280 
281         res = AudioQueueSetParameter (
282             aqPlayerState.mQueue,
283             kAudioQueueParam_Volume,
284             gain
285         );
286 
287         if(res) std::cerr << "AudioQueueSetParameter: Error " << res << std::endl;
288 
289         atomic_set(&(aqPlayerState.mIsRunning), 1);
290         FillBuffers();
291         PrimeAudioQueue();
292 
293         res = AudioQueueStart(aqPlayerState.mQueue, NULL);
294         if(res) {
295             String s = String("AudioQueueStart: Error ") + ToString(res);
296             throw Exception(s);
297         }
298     }
299 
DestroyAudioQueue()300     void AudioOutputDeviceCoreAudio::DestroyAudioQueue() {
301         AudioQueueFlush(aqPlayerState.mQueue);
302         AudioQueueStop (aqPlayerState.mQueue, true);
303         AudioQueueDispose(aqPlayerState.mQueue, true);
304         aqPlayerState.mQueue = NULL;
305     }
306 
307     /**
308      * Entry point for the thread.
309      */
Main()310     int AudioOutputDeviceCoreAudio::Main() {
311         dmsg(1,("CoreAudio thread started\n"));
312 
313         #if DEBUG
314         Thread::setNameOfCaller("CoreAudio");
315         #endif
316 
317         OSStatus res;
318         if(aqPlayerState.mQueue == NULL) {
319             /*
320              * Need to be run from this thread because of CFRunLoopGetCurrent()
321              * which returns the CFRunLoop object for the current thread.
322              */
323             try { CreateAndStartAudioQueue(); }
324             catch(Exception e) {
325                 std::cerr << "Failed to star audio queue: " + e.Message() << std::endl;
326                 return 0;
327             }
328         }
329 
330         {
331             LockGuard lock(destroyMutex);
332             do {
333                 if(atomic_read(&pausedNew) != pausedOld) {
334                     pausedOld = atomic_read(&pausedNew);
335 
336                     if(pausedOld) {
337                         res = AudioQueuePause(aqPlayerState.mQueue);
338                         if(res) std::cerr << "AudioQueuePause: Error " << res << std::endl;
339                     } else {
340                         res = AudioQueuePrime(aqPlayerState.mQueue, 0, NULL);
341                         if(res) std::cerr << "AudioQueuePrime: Error " << res << std::endl;
342                         res = AudioQueueStart(aqPlayerState.mQueue, NULL);
343                         if(res) std::cerr << "AudioQueueStart: Error " << res << std::endl;
344                     }
345                 }
346 
347                 if(atomic_read(&restartQueue)) {
348                     DestroyAudioQueue();
349                     CreateAndStartAudioQueue();
350                     atomic_set(&restartQueue, 0);
351                     dmsg(1,("Audio queue restarted"));
352                 }
353 
354                 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.2, false);
355             } while (atomic_read(&(aqPlayerState.mIsRunning)));
356         }
357 
358         dmsg(2,("CoreAudio thread stopped\n"));
359 
360         pthread_exit(NULL);
361         return 0;
362     }
363 
364 
365 // *************** ParameterDevice ***************
366 // *
367 
ParameterDevice()368     AudioOutputDeviceCoreAudio::ParameterDevice::ParameterDevice() : DeviceCreationParameterString() {
369         InitWithDefault(); // use default device
370     }
371 
ParameterDevice(String s)372     AudioOutputDeviceCoreAudio::ParameterDevice::ParameterDevice(String s)
373             throw (Exception) : DeviceCreationParameterString(s) {
374     }
375 
Description()376     String AudioOutputDeviceCoreAudio::ParameterDevice::Description() {
377         return "Output device to be used";
378     }
379 
Fix()380     bool AudioOutputDeviceCoreAudio::ParameterDevice::Fix() {
381         return true;
382     }
383 
Mandatory()384     bool AudioOutputDeviceCoreAudio::ParameterDevice::Mandatory() {
385         return false;
386     }
387 
388     std::map<String,DeviceCreationParameter*>
DependsAsParameters()389     AudioOutputDeviceCoreAudio::ParameterDevice::DependsAsParameters() {
390         return std::map<String,DeviceCreationParameter*>(); // no dependencies
391     }
392 
393     optional<String>
DefaultAsString(std::map<String,String> Parameters)394     AudioOutputDeviceCoreAudio::ParameterDevice::DefaultAsString(std::map<String,String> Parameters) {
395         CAAudioDeviceListModel* devs = CAAudioDeviceListModel::GetModel();
396         if (devs->GetOutputDeviceCount() < 1) {
397             throw Exception("AudioOutputDeviceCoreAudio: Can't find any output device");
398         }
399         UInt32 idx = devs->GetOutputDeviceIndex(devs->GetDefaultOutputDeviceID());
400         return CreateDeviceName(idx);
401     }
402 
403     std::vector<String>
PossibilitiesAsString(std::map<String,String> Parameters)404     AudioOutputDeviceCoreAudio::ParameterDevice::PossibilitiesAsString(std::map<String,String> Parameters) {
405         std::vector<String> deviceNames;
406 
407         CAAudioDeviceListModel* devs = CAAudioDeviceListModel::GetModel();
408         for(int i = 0; i < devs->GetOutputDeviceCount(); i++) {
409             if(devs->GetOutputDevice(i).GetChannelNumber() < 1) continue;
410 
411             deviceNames.push_back(CreateDeviceName(i));
412         }
413 
414         return deviceNames;
415     }
416 
CreateDeviceName(int devIndex)417     String AudioOutputDeviceCoreAudio::ParameterDevice::CreateDeviceName(int devIndex) {
418         CAAudioDeviceListModel* devs = CAAudioDeviceListModel::GetModel();
419         // Note that the space " " is used as delimiter to obtain the
420         // device index. See GetDeviceIndex()
421         return ToString(devIndex + 1) + " " + devs->GetOutputDevice(devIndex).GetName();
422     }
423 
OnSetValue(String s)424     void AudioOutputDeviceCoreAudio::ParameterDevice::OnSetValue(String s) throw (Exception) {
425         // not posssible, as parameter is fix
426     }
427 
Name()428     String AudioOutputDeviceCoreAudio::ParameterDevice::Name() {
429         return "DEVICE";
430     }
431 
GetDeviceIndex()432     int AudioOutputDeviceCoreAudio::ParameterDevice::GetDeviceIndex() {
433         String s = ValueAsString();
434         if(s.empty()) return -1;
435         int n = (int) s.find(' ');
436         s = s.substr(0, n);
437         return ToInt(s) - 1;
438     }
439 
440 // *************** ParameterSampleRate ***************
441 // *
442 
ParameterSampleRate()443     AudioOutputDeviceCoreAudio::ParameterSampleRate::ParameterSampleRate() :
444                 AudioOutputDevice::ParameterSampleRate::ParameterSampleRate() {
445 
446     }
447 
ParameterSampleRate(String s)448     AudioOutputDeviceCoreAudio::ParameterSampleRate::ParameterSampleRate(String s) :
449                 AudioOutputDevice::ParameterSampleRate::ParameterSampleRate(s) {
450 
451     }
452 
453     std::map<String,DeviceCreationParameter*>
DependsAsParameters()454     AudioOutputDeviceCoreAudio::ParameterSampleRate::DependsAsParameters() {
455         static ParameterDevice device;
456         std::map<String,DeviceCreationParameter*> dependencies;
457         dependencies[device.Name()] = &device;
458         return dependencies;
459     }
460 
461     optional<int>
DefaultAsInt(std::map<String,String> Parameters)462     AudioOutputDeviceCoreAudio::ParameterSampleRate::DefaultAsInt(std::map<String,String> Parameters) {
463         dmsg(2,("AudioOutputDeviceCoreAudio::ParameterSampleRate::DefaultAsInt()\n"));
464         ParameterDevice dev(Parameters["DEVICE"]);
465         int samplerate = 44100;
466 
467         try {
468             int idx = dev.GetDeviceIndex();
469 
470             CAAudioDeviceListModel* devs = CAAudioDeviceListModel::GetModel();
471             samplerate = devs->GetOutputDevice(idx).GetDefaultSamplerate();
472         } catch(Exception e) { }
473 
474         return samplerate;
475     }
476 
477     std::vector<int>
PossibilitiesAsInt(std::map<String,String> Parameters)478     AudioOutputDeviceCoreAudio::ParameterSampleRate::PossibilitiesAsInt(std::map<String,String> Parameters) {
479         ParameterDevice dev(Parameters["DEVICE"]);
480         std::vector<int> srates;
481 
482         try {
483             int idx = dev.GetDeviceIndex();
484             CAAudioDeviceListModel* devs = CAAudioDeviceListModel::GetModel();
485             srates = devs->GetOutputDevice(idx).GetNominalSamplerates();
486         } catch(Exception x) { }
487 
488         return srates;
489     }
490 
491 
492 // *************** ParameterChannels ***************
493 // *
494 
ParameterChannels()495     AudioOutputDeviceCoreAudio::ParameterChannels::ParameterChannels() :
496                     AudioOutputDevice::ParameterChannels::ParameterChannels() {
497 
498     }
499 
ParameterChannels(String s)500     AudioOutputDeviceCoreAudio::ParameterChannels::ParameterChannels(String s) :
501                     AudioOutputDevice::ParameterChannels::ParameterChannels(s) {
502 
503     }
504 
505     optional<int>
DefaultAsInt(std::map<String,String> Parameters)506     AudioOutputDeviceCoreAudio::ParameterChannels::DefaultAsInt(std::map<String,String> Parameters) {
507         dmsg(2,("AudioOutputDeviceCoreAudio::ParameterChannels::DefaultAsInt()\n"));
508         ParameterDevice dev(Parameters["DEVICE"]);
509         int chns = 2;
510 
511         try {
512             int idx = dev.GetDeviceIndex();
513             CAAudioDeviceListModel* devs = CAAudioDeviceListModel::GetModel();
514             chns = devs->GetOutputDevice(idx).GetChannelNumber();
515         } catch(Exception e) { }
516 
517         return chns;
518     }
519 
520     std::vector<int>
PossibilitiesAsInt(std::map<String,String> Parameters)521     AudioOutputDeviceCoreAudio::ParameterChannels::PossibilitiesAsInt(std::map<String,String> Parameters) {
522         ParameterDevice dev(Parameters["DEVICE"]);
523         std::vector<int> chns;
524 
525         try {
526             int idx = dev.GetDeviceIndex();
527             CAAudioDeviceListModel* devs = CAAudioDeviceListModel::GetModel();
528             for(int i = 1; i <= devs->GetOutputDevice(idx).GetChannelNumber(); i++) {
529                 chns.push_back(i);
530             }
531         } catch(Exception x) { }
532 
533         return chns;
534     }
535 
536 // *************** ParameterBuffers ***************
537 // *
538 
ParameterBuffers()539     AudioOutputDeviceCoreAudio::ParameterBuffers::ParameterBuffers() : DeviceCreationParameterInt() {
540         InitWithDefault();
541     }
542 
ParameterBuffers(String s)543     AudioOutputDeviceCoreAudio::ParameterBuffers::ParameterBuffers(String s)
544             throw (Exception) : DeviceCreationParameterInt(s) {
545     }
546 
Description()547     String AudioOutputDeviceCoreAudio::ParameterBuffers::Description() {
548         return "Number of audio buffer";
549     }
550 
Fix()551     bool AudioOutputDeviceCoreAudio::ParameterBuffers::Fix() {
552         return true;
553     }
554 
Mandatory()555     bool AudioOutputDeviceCoreAudio::ParameterBuffers::Mandatory() {
556         return false;
557     }
558 
559     std::map<String,DeviceCreationParameter*>
DependsAsParameters()560     AudioOutputDeviceCoreAudio::ParameterBuffers::DependsAsParameters() {
561         return std::map<String,DeviceCreationParameter*>();
562     }
563 
564     optional<int>
DefaultAsInt(std::map<String,String> Parameters)565     AudioOutputDeviceCoreAudio::ParameterBuffers::DefaultAsInt(std::map<String,String> Parameters) {
566         return 3;
567     }
568 
569     optional<int>
RangeMinAsInt(std::map<String,String> Parameters)570     AudioOutputDeviceCoreAudio::ParameterBuffers::RangeMinAsInt(std::map<String,String> Parameters) {
571         return 2;
572     }
573 
574     optional<int>
RangeMaxAsInt(std::map<String,String> Parameters)575     AudioOutputDeviceCoreAudio::ParameterBuffers::RangeMaxAsInt(std::map<String,String> Parameters) {
576         return 16;
577     }
578 
579     std::vector<int>
PossibilitiesAsInt(std::map<String,String> Parameters)580     AudioOutputDeviceCoreAudio::ParameterBuffers::PossibilitiesAsInt(std::map<String,String> Parameters) {
581         return std::vector<int>();
582     }
583 
OnSetValue(int i)584     void AudioOutputDeviceCoreAudio::ParameterBuffers::OnSetValue(int i) throw (Exception) {
585         // not posssible, as parameter is fix
586     }
587 
Name()588     String AudioOutputDeviceCoreAudio::ParameterBuffers::Name() {
589         return "BUFFERS";
590     }
591 
592 // *************** ParameterBufferSize ***************
593 // *
594 
ParameterBufferSize()595     AudioOutputDeviceCoreAudio::ParameterBufferSize::ParameterBufferSize() : DeviceCreationParameterInt() {
596         InitWithDefault();
597     }
598 
ParameterBufferSize(String s)599     AudioOutputDeviceCoreAudio::ParameterBufferSize::ParameterBufferSize(String s)
600             throw (Exception) : DeviceCreationParameterInt(s) {
601     }
602 
Description()603     String AudioOutputDeviceCoreAudio::ParameterBufferSize::Description() {
604         return "Size of the audio buffer in sample frames";
605     }
606 
Fix()607     bool AudioOutputDeviceCoreAudio::ParameterBufferSize::Fix() {
608         return true;
609     }
610 
Mandatory()611     bool AudioOutputDeviceCoreAudio::ParameterBufferSize::Mandatory() {
612         return false;
613     }
614 
615     std::map<String,DeviceCreationParameter*>
DependsAsParameters()616     AudioOutputDeviceCoreAudio::ParameterBufferSize::DependsAsParameters() {
617         return std::map<String,DeviceCreationParameter*>();
618     }
619 
620     optional<int>
DefaultAsInt(std::map<String,String> Parameters)621     AudioOutputDeviceCoreAudio::ParameterBufferSize::DefaultAsInt(std::map<String,String> Parameters) {
622         return 256;
623     }
624 
625     optional<int>
RangeMinAsInt(std::map<String,String> Parameters)626     AudioOutputDeviceCoreAudio::ParameterBufferSize::RangeMinAsInt(std::map<String,String> Parameters) {
627         return 32;
628     }
629 
630     optional<int>
RangeMaxAsInt(std::map<String,String> Parameters)631     AudioOutputDeviceCoreAudio::ParameterBufferSize::RangeMaxAsInt(std::map<String,String> Parameters) {
632         return 4096;
633     }
634 
635     std::vector<int>
PossibilitiesAsInt(std::map<String,String> Parameters)636     AudioOutputDeviceCoreAudio::ParameterBufferSize::PossibilitiesAsInt(std::map<String,String> Parameters) {
637         return std::vector<int>();
638     }
639 
OnSetValue(int i)640     void AudioOutputDeviceCoreAudio::ParameterBufferSize::OnSetValue(int i) throw (Exception) {
641         // not posssible, as parameter is fix
642     }
643 
Name()644     String AudioOutputDeviceCoreAudio::ParameterBufferSize::Name() {
645         return "BUFFERSIZE";
646     }
647 } // namespace LinuxSampler
648