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