26 |
|
|
27 |
namespace LinuxSampler { |
namespace LinuxSampler { |
28 |
|
|
29 |
|
void AudioOutputDeviceCoreAudio::AudioQueueListener ( |
30 |
|
void *inUserData, AudioQueueRef inAQ, AudioQueuePropertyID inID |
31 |
|
) { |
32 |
|
switch(inID) { |
33 |
|
case kAudioQueueProperty_IsRunning: |
34 |
|
|
35 |
|
break; |
36 |
|
case kAudioQueueProperty_CurrentDevice: |
37 |
|
|
38 |
|
break; |
39 |
|
} |
40 |
|
} |
41 |
|
|
42 |
void AudioOutputDeviceCoreAudio::HandleOutputBuffer ( |
void AudioOutputDeviceCoreAudio::HandleOutputBuffer ( |
43 |
void *aqData, |
void *aqData, |
44 |
AudioQueueRef inAQ, |
AudioQueueRef inAQ, |
50 |
AudioQueueStop (pAqData->mQueue, true); |
AudioQueueStop (pAqData->mQueue, true); |
51 |
return; |
return; |
52 |
} |
} |
53 |
|
|
54 |
|
if(atomic_read(&(pAqData->pDevice->restartQueue))) return; |
55 |
|
|
56 |
uint bufferSize = pAqData->pDevice->uiBufferSize; |
uint bufferSize = pAqData->pDevice->uiBufferSize; |
57 |
|
|
58 |
// let all connected engines render 'fragmentSize' sample points |
// let all connected engines render 'fragmentSize' sample points |
79 |
if(res) std::cerr << "AudioQueueEnqueueBuffer: Error " << res << std::endl; |
if(res) std::cerr << "AudioQueueEnqueueBuffer: Error " << res << std::endl; |
80 |
} |
} |
81 |
|
|
82 |
AudioOutputDeviceCoreAudio::DeviceInfo* AudioOutputDeviceCoreAudio::pDeviceInfo = NULL; |
void AudioOutputDeviceCoreAudio::DeviceChanged() { |
83 |
|
dmsg(1,("Restarting audio queue...")); |
84 |
AudioOutputDeviceCoreAudio::DeviceInfo* AudioOutputDeviceCoreAudio::GetDeviceInfo() { |
atomic_set(&restartQueue, 1); |
|
if(pDeviceInfo == NULL) { |
|
|
pDeviceInfo = new DeviceInfo; |
|
|
|
|
|
pDeviceInfo->uiSamplerate = 44100; |
|
|
pDeviceInfo->uiChannelNumber = 2; |
|
|
|
|
|
AudioStreamBasicDescription dataFormat; |
|
|
SetAudioDataFormat(&dataFormat); |
|
|
AudioQueueRef pQueue = NULL; |
|
|
|
|
|
OSStatus res = AudioQueueNewOutput ( |
|
|
&dataFormat, NULL, NULL, NULL, NULL, 0, &pQueue |
|
|
); |
|
|
|
|
|
if(res) { |
|
|
std::cerr << "Failed to retrieve device info: " << res << std::endl; |
|
|
return pDeviceInfo; |
|
|
} |
|
|
|
|
|
UInt32 chns = pDeviceInfo->uiChannelNumber; |
|
|
UInt32 size = sizeof(chns); |
|
|
res = AudioQueueGetProperty ( |
|
|
pQueue, |
|
|
kAudioQueueDeviceProperty_NumberChannels, |
|
|
&chns, &size |
|
|
); |
|
|
|
|
|
if(res) std::cerr << "Failed to retrieve channel number: " << res << std::endl; |
|
|
else pDeviceInfo->uiChannelNumber = chns; |
|
|
|
|
|
Float64 sRate = pDeviceInfo->uiSamplerate; |
|
|
size = sizeof(sRate); |
|
|
res = AudioQueueGetProperty ( |
|
|
pQueue, |
|
|
kAudioQueueDeviceProperty_SampleRate, |
|
|
&sRate, &size |
|
|
); |
|
|
|
|
|
if(res) std::cerr << "Failed to retrieve samplerate: " << res << std::endl; |
|
|
else pDeviceInfo->uiSamplerate = (uint)sRate; |
|
|
|
|
|
AudioQueueDispose(pQueue, true); |
|
|
} |
|
|
|
|
|
return pDeviceInfo; |
|
85 |
} |
} |
86 |
|
|
87 |
AudioOutputDeviceCoreAudio::AudioOutputDeviceCoreAudio ( |
AudioOutputDeviceCoreAudio::AudioOutputDeviceCoreAudio ( |
88 |
std::map<String,DeviceCreationParameter*> Parameters |
std::map<String,DeviceCreationParameter*> Parameters |
89 |
) : AudioOutputDevice(Parameters), Thread(true, true, 1, 0) { |
) : AudioOutputDevice(Parameters), Thread(true, true, 1, 0), CurrentDevice(0) { |
90 |
|
|
91 |
dmsg(2,("AudioOutputDeviceCoreAudio::AudioOutputDeviceCoreAudio()\n")); |
dmsg(2,("AudioOutputDeviceCoreAudio::AudioOutputDeviceCoreAudio()\n")); |
92 |
|
if(CAAudioDeviceListModel::GetModel()->GetOutputDeviceCount() < 1) { |
93 |
|
throw Exception("No audio output device found"); |
94 |
|
} |
95 |
atomic_set(&pausedNew, 0); |
atomic_set(&pausedNew, 0); |
96 |
pausedOld = 0; |
pausedOld = 0; |
97 |
|
atomic_set(&restartQueue, 0); |
98 |
|
|
99 |
uiCoreAudioChannels = ((DeviceCreationParameterInt*)Parameters["CHANNELS"])->ValueAsInt(); |
uiCoreAudioChannels = ((DeviceCreationParameterInt*)Parameters["CHANNELS"])->ValueAsInt(); |
100 |
uint samplerate = ((DeviceCreationParameterInt*)Parameters["SAMPLERATE"])->ValueAsInt(); |
uint samplerate = ((DeviceCreationParameterInt*)Parameters["SAMPLERATE"])->ValueAsInt(); |
101 |
uiBufferNumber = ((DeviceCreationParameterInt*)Parameters["BUFFERS"])->ValueAsInt(); |
uiBufferNumber = ((DeviceCreationParameterInt*)Parameters["BUFFERS"])->ValueAsInt(); |
102 |
uiBufferSize = ((DeviceCreationParameterInt*)Parameters["BUFFERSIZE"])->ValueAsInt(); |
uiBufferSize = ((DeviceCreationParameterInt*)Parameters["BUFFERSIZE"])->ValueAsInt(); |
103 |
|
int device = 0; |
104 |
|
try { device = ((ParameterDevice*)Parameters["DEVICE"])->GetDeviceIndex(); } |
105 |
|
catch(Exception x) { } |
106 |
|
|
107 |
|
CurrentDevice = CAAudioDeviceListModel::GetModel()->GetOutputDevice(device); |
108 |
|
CurrentDevice.AddListener(this); |
109 |
|
|
110 |
aqPlayerState.mDataFormat.mSampleRate = samplerate; |
aqPlayerState.mDataFormat.mSampleRate = samplerate; |
111 |
aqPlayerState.mDataFormat.mFormatID = kAudioFormatLinearPCM; |
aqPlayerState.mDataFormat.mFormatID = kAudioFormatLinearPCM; |
148 |
AudioQueueDispose(aqPlayerState.mQueue, true); |
AudioQueueDispose(aqPlayerState.mQueue, true); |
149 |
destroyMutex.Unlock(); |
destroyMutex.Unlock(); |
150 |
delete [] aqPlayerState.mBuffers; |
delete [] aqPlayerState.mBuffers; |
151 |
|
|
152 |
|
CurrentDevice.RemoveListener(this); |
153 |
} |
} |
154 |
|
|
155 |
void AudioOutputDeviceCoreAudio::SetAudioDataFormat(AudioStreamBasicDescription* pDataFormat) { |
void AudioOutputDeviceCoreAudio::SetAudioDataFormat(AudioStreamBasicDescription* pDataFormat) { |
175 |
} |
} |
176 |
|
|
177 |
String AudioOutputDeviceCoreAudio::Version() { |
String AudioOutputDeviceCoreAudio::Version() { |
178 |
String s = "$Revision: 1.1 $"; |
String s = "$Revision: 1.2 $"; |
179 |
return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword |
return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword |
180 |
} |
} |
181 |
|
|
208 |
return new AudioChannel(ChannelNr, Channel(ChannelNr % uiCoreAudioChannels)); |
return new AudioChannel(ChannelNr, Channel(ChannelNr % uiCoreAudioChannels)); |
209 |
} |
} |
210 |
|
|
211 |
/** |
void AudioOutputDeviceCoreAudio::FillBuffers() { |
212 |
* Entry point for the thread. |
for (int i = 0; i < uiBufferNumber; ++i) { |
213 |
*/ |
HandleOutputBuffer ( |
|
int AudioOutputDeviceCoreAudio::Main() { |
|
|
dmsg(2,("CoreAudio thread started\n")); |
|
|
|
|
|
bool initialized = aqPlayerState.mQueue != NULL; |
|
|
if(!initialized) { |
|
|
/* |
|
|
* Initializing the audio queue |
|
|
* Need to be run from this thread because of CFRunLoopGetCurrent() |
|
|
* which returns the CFRunLoop object for the current thread. |
|
|
*/ |
|
|
OSStatus res = AudioQueueNewOutput ( |
|
|
&aqPlayerState.mDataFormat, |
|
|
HandleOutputBuffer, |
|
214 |
&aqPlayerState, |
&aqPlayerState, |
215 |
CFRunLoopGetCurrent(), |
aqPlayerState.mQueue, |
216 |
kCFRunLoopCommonModes, |
aqPlayerState.mBuffers[i] |
|
0, |
|
|
&aqPlayerState.mQueue |
|
217 |
); |
); |
218 |
|
} |
219 |
|
} |
220 |
|
|
221 |
if(res) { |
void AudioOutputDeviceCoreAudio::PrimeAudioQueue() { |
222 |
String s = String("AudioQueueNewOutput: Error ") + ToString(res); |
OSStatus res = AudioQueuePrime(aqPlayerState.mQueue, 0, NULL); |
223 |
throw Exception(s); |
if(res) { |
224 |
} |
String s = String("AudioQueuePrime: Error ") + ToString(res); |
225 |
|
throw Exception(s); |
226 |
|
} |
227 |
|
} |
228 |
|
|
229 |
for (int i = 0; i < uiBufferNumber; ++i) { |
void AudioOutputDeviceCoreAudio::CreateAndStartAudioQueue() { |
230 |
OSStatus res = AudioQueueAllocateBuffer ( |
OSStatus res = AudioQueueNewOutput ( |
231 |
aqPlayerState.mQueue, |
&aqPlayerState.mDataFormat, |
232 |
aqPlayerState.bufferByteSize, |
HandleOutputBuffer, |
233 |
&aqPlayerState.mBuffers[i] |
&aqPlayerState, |
234 |
); |
CFRunLoopGetCurrent(), |
235 |
|
kCFRunLoopCommonModes, |
236 |
if(res) { |
0, |
237 |
String s = String("AudioQueueAllocateBuffer: Error "); |
&aqPlayerState.mQueue |
238 |
throw Exception(s + ToString(res)); |
); |
239 |
} |
|
240 |
} |
if(res) { |
241 |
|
String s = String("AudioQueueNewOutput: Error ") + ToString(res); |
242 |
|
throw Exception(s); |
243 |
|
} |
244 |
|
|
245 |
|
CFStringRef devUID = CFStringCreateWithCString ( |
246 |
|
NULL, CurrentDevice.GetUID().c_str(), kCFStringEncodingASCII |
247 |
|
); |
248 |
|
res = AudioQueueSetProperty ( |
249 |
|
aqPlayerState.mQueue, |
250 |
|
kAudioQueueProperty_CurrentDevice, |
251 |
|
&devUID, sizeof(CFStringRef) |
252 |
|
); |
253 |
|
CFRelease(devUID); |
254 |
|
|
255 |
|
if(res) { |
256 |
|
String s = String("Failed to set audio device: ") + ToString(res); |
257 |
|
throw Exception(s); |
258 |
} |
} |
259 |
|
|
260 |
for (int i = 0; i < uiBufferNumber; ++i) { |
for (int i = 0; i < uiBufferNumber; ++i) { |
261 |
HandleOutputBuffer ( |
res = AudioQueueAllocateBuffer ( |
|
&aqPlayerState, |
|
262 |
aqPlayerState.mQueue, |
aqPlayerState.mQueue, |
263 |
aqPlayerState.mBuffers[i] |
aqPlayerState.bufferByteSize, |
264 |
|
&aqPlayerState.mBuffers[i] |
265 |
); |
); |
266 |
|
|
267 |
|
if(res) { |
268 |
|
String s = String("AudioQueueAllocateBuffer: Error "); |
269 |
|
throw Exception(s + ToString(res)); |
270 |
|
} |
271 |
} |
} |
272 |
|
|
273 |
|
res = AudioQueueAddPropertyListener ( |
274 |
|
aqPlayerState.mQueue, |
275 |
|
kAudioQueueProperty_CurrentDevice, |
276 |
|
AudioQueueListener, |
277 |
|
NULL |
278 |
|
); |
279 |
|
if(res) std::cerr << "Failed to register device change listener: " << res << std::endl; |
280 |
|
|
281 |
|
res = AudioQueueAddPropertyListener ( |
282 |
|
aqPlayerState.mQueue, |
283 |
|
kAudioQueueProperty_IsRunning, |
284 |
|
AudioQueueListener, |
285 |
|
NULL |
286 |
|
); |
287 |
|
if(res) std::cerr << "Failed to register running listener: " << res << std::endl; |
288 |
|
|
289 |
Float32 gain = 1.0; |
Float32 gain = 1.0; |
290 |
|
|
291 |
OSStatus res = AudioQueueSetParameter ( |
res = AudioQueueSetParameter ( |
292 |
aqPlayerState.mQueue, |
aqPlayerState.mQueue, |
293 |
kAudioQueueParam_Volume, |
kAudioQueueParam_Volume, |
294 |
gain |
gain |
297 |
if(res) std::cerr << "AudioQueueSetParameter: Error " << res << std::endl; |
if(res) std::cerr << "AudioQueueSetParameter: Error " << res << std::endl; |
298 |
|
|
299 |
atomic_set(&(aqPlayerState.mIsRunning), 1); |
atomic_set(&(aqPlayerState.mIsRunning), 1); |
300 |
|
FillBuffers(); |
301 |
if(!initialized) { |
PrimeAudioQueue(); |
|
res = AudioQueuePrime(aqPlayerState.mQueue, 0, NULL); |
|
|
if(res) { |
|
|
String s = String("AudioQueuePrime: Error ") + ToString(res); |
|
|
throw Exception(s); |
|
|
} |
|
|
} |
|
302 |
|
|
303 |
res = AudioQueueStart(aqPlayerState.mQueue, NULL); |
res = AudioQueueStart(aqPlayerState.mQueue, NULL); |
304 |
if(res) { |
if(res) { |
305 |
String s = String("AudioQueueStart: Error ") + ToString(res); |
String s = String("AudioQueueStart: Error ") + ToString(res); |
306 |
throw Exception(s); |
throw Exception(s); |
307 |
} |
} |
308 |
|
} |
309 |
|
|
310 |
|
void AudioOutputDeviceCoreAudio::DestroyAudioQueue() { |
311 |
|
AudioQueueFlush(aqPlayerState.mQueue); |
312 |
|
AudioQueueStop (aqPlayerState.mQueue, true); |
313 |
|
AudioQueueDispose(aqPlayerState.mQueue, true); |
314 |
|
aqPlayerState.mQueue = NULL; |
315 |
|
} |
316 |
|
|
317 |
|
/** |
318 |
|
* Entry point for the thread. |
319 |
|
*/ |
320 |
|
int AudioOutputDeviceCoreAudio::Main() { |
321 |
|
dmsg(2,("CoreAudio thread started\n")); |
322 |
|
OSStatus res; |
323 |
|
std::cout<<"thread started ca\n"; |
324 |
|
if(aqPlayerState.mQueue == NULL) { |
325 |
|
/* |
326 |
|
* Need to be run from this thread because of CFRunLoopGetCurrent() |
327 |
|
* which returns the CFRunLoop object for the current thread. |
328 |
|
*/ |
329 |
|
CreateAndStartAudioQueue(); |
330 |
|
} |
331 |
|
|
332 |
destroyMutex.Lock(); |
destroyMutex.Lock(); |
333 |
do { |
do { |
344 |
if(res) std::cerr << "AudioQueueStart: Error " << res << std::endl; |
if(res) std::cerr << "AudioQueueStart: Error " << res << std::endl; |
345 |
} |
} |
346 |
} |
} |
347 |
|
|
348 |
|
if(atomic_read(&restartQueue)) { |
349 |
|
DestroyAudioQueue(); |
350 |
|
try { CreateAndStartAudioQueue(); } |
351 |
|
catch(Exception e) { |
352 |
|
destroyMutex.Unlock(); |
353 |
|
throw e; |
354 |
|
} |
355 |
|
atomic_set(&restartQueue, 0); |
356 |
|
dmsg(1,("Audio queue restarted")); |
357 |
|
} |
358 |
|
|
359 |
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.2, false); |
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.2, false); |
360 |
} while (atomic_read(&(aqPlayerState.mIsRunning))); |
} while (atomic_read(&(aqPlayerState.mIsRunning))); |
366 |
} |
} |
367 |
|
|
368 |
|
|
369 |
|
// *************** ParameterDevice *************** |
370 |
|
// * |
371 |
|
|
372 |
|
AudioOutputDeviceCoreAudio::ParameterDevice::ParameterDevice() : DeviceCreationParameterString() { |
373 |
|
InitWithDefault(); // use default device |
374 |
|
} |
375 |
|
|
376 |
|
AudioOutputDeviceCoreAudio::ParameterDevice::ParameterDevice(String s) |
377 |
|
throw (Exception) : DeviceCreationParameterString(s) { |
378 |
|
} |
379 |
|
|
380 |
|
String AudioOutputDeviceCoreAudio::ParameterDevice::Description() { |
381 |
|
return "Output device to be used"; |
382 |
|
} |
383 |
|
|
384 |
|
bool AudioOutputDeviceCoreAudio::ParameterDevice::Fix() { |
385 |
|
return true; |
386 |
|
} |
387 |
|
|
388 |
|
bool AudioOutputDeviceCoreAudio::ParameterDevice::Mandatory() { |
389 |
|
return false; |
390 |
|
} |
391 |
|
|
392 |
|
std::map<String,DeviceCreationParameter*> |
393 |
|
AudioOutputDeviceCoreAudio::ParameterDevice::DependsAsParameters() { |
394 |
|
return std::map<String,DeviceCreationParameter*>(); // no dependencies |
395 |
|
} |
396 |
|
|
397 |
|
optional<String> |
398 |
|
AudioOutputDeviceCoreAudio::ParameterDevice::DefaultAsString(std::map<String,String> Parameters) { |
399 |
|
CAAudioDeviceListModel* devs = CAAudioDeviceListModel::GetModel(); |
400 |
|
if (devs->GetOutputDeviceCount() < 1) { |
401 |
|
throw Exception("AudioOutputDeviceCoreAudio: Can't find any output device"); |
402 |
|
} |
403 |
|
UInt32 idx = devs->GetOutputDeviceIndex(devs->GetDefaultOutputDeviceID()); |
404 |
|
return CreateDeviceName(idx); |
405 |
|
} |
406 |
|
|
407 |
|
std::vector<String> |
408 |
|
AudioOutputDeviceCoreAudio::ParameterDevice::PossibilitiesAsString(std::map<String,String> Parameters) { |
409 |
|
std::vector<String> deviceNames; |
410 |
|
|
411 |
|
CAAudioDeviceListModel* devs = CAAudioDeviceListModel::GetModel(); |
412 |
|
for(int i = 0; i < devs->GetOutputDeviceCount(); i++) { |
413 |
|
if(devs->GetOutputDevice(i).GetChannelNumber() < 1) continue; |
414 |
|
|
415 |
|
deviceNames.push_back(CreateDeviceName(i)); |
416 |
|
} |
417 |
|
|
418 |
|
return deviceNames; |
419 |
|
} |
420 |
|
|
421 |
|
String AudioOutputDeviceCoreAudio::ParameterDevice::CreateDeviceName(int devIndex) { |
422 |
|
CAAudioDeviceListModel* devs = CAAudioDeviceListModel::GetModel(); |
423 |
|
// Note that the space " " is used as delimiter to obtain the |
424 |
|
// device index. See GetDeviceIndex() |
425 |
|
return ToString(devIndex + 1) + " " + devs->GetOutputDevice(devIndex).GetName(); |
426 |
|
} |
427 |
|
|
428 |
|
void AudioOutputDeviceCoreAudio::ParameterDevice::OnSetValue(String s) throw (Exception) { |
429 |
|
// not posssible, as parameter is fix |
430 |
|
} |
431 |
|
|
432 |
|
String AudioOutputDeviceCoreAudio::ParameterDevice::Name() { |
433 |
|
return "DEVICE"; |
434 |
|
} |
435 |
|
|
436 |
|
int AudioOutputDeviceCoreAudio::ParameterDevice::GetDeviceIndex() { |
437 |
|
String s = ValueAsString(); |
438 |
|
if(s.empty()) return -1; |
439 |
|
int n = s.find(' '); |
440 |
|
s = s.substr(0, n); |
441 |
|
return ToInt(s) - 1; |
442 |
|
} |
443 |
|
|
444 |
// *************** ParameterSampleRate *************** |
// *************** ParameterSampleRate *************** |
445 |
// * |
// * |
446 |
|
|
454 |
|
|
455 |
} |
} |
456 |
|
|
457 |
|
std::map<String,DeviceCreationParameter*> |
458 |
|
AudioOutputDeviceCoreAudio::ParameterSampleRate::DependsAsParameters() { |
459 |
|
static ParameterDevice device; |
460 |
|
std::map<String,DeviceCreationParameter*> dependencies; |
461 |
|
dependencies[device.Name()] = &device; |
462 |
|
return dependencies; |
463 |
|
} |
464 |
|
|
465 |
optional<int> |
optional<int> |
466 |
AudioOutputDeviceCoreAudio::ParameterSampleRate::DefaultAsInt(std::map<String,String> Parameters) { |
AudioOutputDeviceCoreAudio::ParameterSampleRate::DefaultAsInt(std::map<String,String> Parameters) { |
467 |
dmsg(2,("AudioOutputDeviceCoreAudio::ParameterSampleRate::DefaultAsInt()\n")); |
dmsg(2,("AudioOutputDeviceCoreAudio::ParameterSampleRate::DefaultAsInt()\n")); |
468 |
return GetDeviceInfo()->uiSamplerate; |
ParameterDevice dev(Parameters["DEVICE"]); |
469 |
|
int samplerate = 44100; |
470 |
|
|
471 |
|
try { |
472 |
|
int idx = dev.GetDeviceIndex(); |
473 |
|
|
474 |
|
CAAudioDeviceListModel* devs = CAAudioDeviceListModel::GetModel(); |
475 |
|
samplerate = devs->GetOutputDevice(idx).GetDefaultSamplerate(); |
476 |
|
} catch(Exception e) { } |
477 |
|
|
478 |
|
return samplerate; |
479 |
|
} |
480 |
|
|
481 |
|
std::vector<int> |
482 |
|
AudioOutputDeviceCoreAudio::ParameterSampleRate::PossibilitiesAsInt(std::map<String,String> Parameters) { |
483 |
|
ParameterDevice dev(Parameters["DEVICE"]); |
484 |
|
std::vector<int> srates; |
485 |
|
|
486 |
|
try { |
487 |
|
int idx = dev.GetDeviceIndex(); |
488 |
|
CAAudioDeviceListModel* devs = CAAudioDeviceListModel::GetModel(); |
489 |
|
srates = devs->GetOutputDevice(idx).GetNominalSamplerates(); |
490 |
|
} catch(Exception x) { } |
491 |
|
|
492 |
|
return srates; |
493 |
} |
} |
494 |
|
|
495 |
|
|
509 |
optional<int> |
optional<int> |
510 |
AudioOutputDeviceCoreAudio::ParameterChannels::DefaultAsInt(std::map<String,String> Parameters) { |
AudioOutputDeviceCoreAudio::ParameterChannels::DefaultAsInt(std::map<String,String> Parameters) { |
511 |
dmsg(2,("AudioOutputDeviceCoreAudio::ParameterChannels::DefaultAsInt()\n")); |
dmsg(2,("AudioOutputDeviceCoreAudio::ParameterChannels::DefaultAsInt()\n")); |
512 |
return GetDeviceInfo()->uiChannelNumber; |
ParameterDevice dev(Parameters["DEVICE"]); |
513 |
|
int chns = 2; |
514 |
|
|
515 |
|
try { |
516 |
|
int idx = dev.GetDeviceIndex(); |
517 |
|
CAAudioDeviceListModel* devs = CAAudioDeviceListModel::GetModel(); |
518 |
|
chns = devs->GetOutputDevice(idx).GetChannelNumber(); |
519 |
|
} catch(Exception e) { } |
520 |
|
|
521 |
|
return chns; |
522 |
|
} |
523 |
|
|
524 |
|
std::vector<int> |
525 |
|
AudioOutputDeviceCoreAudio::ParameterChannels::PossibilitiesAsInt(std::map<String,String> Parameters) { |
526 |
|
ParameterDevice dev(Parameters["DEVICE"]); |
527 |
|
std::vector<int> chns; |
528 |
|
|
529 |
|
try { |
530 |
|
int idx = dev.GetDeviceIndex(); |
531 |
|
CAAudioDeviceListModel* devs = CAAudioDeviceListModel::GetModel(); |
532 |
|
for(int i = 1; i <= devs->GetOutputDevice(idx).GetChannelNumber(); i++) { |
533 |
|
chns.push_back(i); |
534 |
|
} |
535 |
|
} catch(Exception x) { } |
536 |
|
|
537 |
|
return chns; |
538 |
} |
} |
539 |
|
|
540 |
// *************** ParameterBuffers *************** |
// *************** ParameterBuffers *************** |