/[svn]/linuxsampler/trunk/src/drivers/audio/CAAudioDeviceModel.cpp
ViewVC logotype

Contents of /linuxsampler/trunk/src/drivers/audio/CAAudioDeviceModel.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1846 - (show annotations) (download)
Thu Feb 26 22:43:45 2009 UTC (15 years, 2 months ago) by iliev
File size: 19974 byte(s)
* AU plugin, work in progress:
* added build files
* fixes in MIDI event handling

1 /***************************************************************************
2 * *
3 * LinuxSampler - modular, streaming capable sampler *
4 * *
5 * Copyright (C) 2009 Grigor Iliev *
6 * *
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program; if not, write to the Free Software *
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
20 * MA 02111-1307 USA *
21 ***************************************************************************/
22
23 #include "CAAudioDeviceModel.h"
24
25 #include <iostream>
26 #include "../../common/Exception.h"
27 #include "../../common/global_private.h"
28
29 namespace LinuxSampler {
30
31 CAAudioDeviceModel::CAAudioDeviceModel(AudioDeviceID Id) {
32 this->Id = Id;
33 ChannelNumber = 2;
34 DefaultSamplerate = 44100;
35
36 charBufSize = 512;
37 charBuf = new char[charBufSize];
38
39 Init();
40 }
41
42 CAAudioDeviceModel::CAAudioDeviceModel(const CAAudioDeviceModel& m) : Uid(m.Uid),
43 Name(m.Name), NominalSamplerates(m.NominalSamplerates), AudioStreams(m.AudioStreams) {
44
45 Id = m.Id;
46 ChannelNumber = m.ChannelNumber;
47 DefaultSamplerate = m.DefaultSamplerate;
48
49 charBufSize = 512;
50 charBuf = new char[charBufSize];
51
52 Init();
53 }
54
55 CAAudioDeviceModel::~CAAudioDeviceModel() {
56 CAAudioDeviceListModel::GetModel()->RemoveListener(this);
57 delete [] charBuf;
58 }
59
60 CAAudioDeviceModel& CAAudioDeviceModel::operator=(const CAAudioDeviceModel& m) {
61 Id = m.Id;
62 Uid = m.Uid;
63 Name = m.Name;
64 ChannelNumber = m.ChannelNumber;
65 DefaultSamplerate = m.DefaultSamplerate;
66 NominalSamplerates = m.NominalSamplerates;
67 AudioStreams = m.AudioStreams;
68
69 return *this;
70 }
71
72 void CAAudioDeviceModel::Init() {
73 CAAudioDeviceListModel::GetModel()->AddListener(this);
74 }
75
76 void CAAudioDeviceModel::DeviceChanged(AudioDeviceID devID) {
77 if(GetID() == devID) FireDeviceChangedEvent();
78 }
79
80 void CAAudioDeviceModel::FireDeviceChangedEvent() {
81 for(int i = 0; i < GetListenerCount(); i++) {
82 GetListener(i)->DeviceChanged();
83 }
84 }
85
86 AudioDeviceID CAAudioDeviceModel::GetID() { return Id; }
87
88 std::string CAAudioDeviceModel::GetUID() { return Uid; }
89
90 void CAAudioDeviceModel::SetUID(CFStringRef s) {
91 Uid = GetStr(s);
92 }
93
94 std::string CAAudioDeviceModel::GetName() { return Name; }
95
96 void CAAudioDeviceModel::SetName(CFStringRef s) {
97 Name = GetStr(s);
98 }
99
100 int CAAudioDeviceModel::GetChannelNumber() { return ChannelNumber; }
101
102 int CAAudioDeviceModel::GetDefaultSamplerate() { return DefaultSamplerate; }
103
104 const std::vector<int> CAAudioDeviceModel::GetNominalSamplerates() {
105 return NominalSamplerates;
106 }
107
108 std::vector<CAAudioStream> CAAudioDeviceModel::GetAudioStreams() {
109 return AudioStreams;
110 }
111
112 std::string CAAudioDeviceModel::GetStr(CFStringRef s) {
113 if(s == NULL) return std::string("Undefined");
114
115 CFRetain(s);
116 CFIndex len = CFStringGetLength(s) + 1;
117 if(charBufSize < len) {
118 delete [] charBuf;
119 charBufSize *= 2;
120 if(charBufSize < len) charBufSize = len;
121 charBuf = new char[charBufSize];
122 }
123
124 std::string s2;
125 if(CFStringGetCString(s, charBuf, charBufSize, kCFStringEncodingASCII)) {
126 s2 = charBuf;
127 }
128 CFRelease(s);
129
130 return s2;
131 }
132
133 //////////////////////////////////////////////////////////////////
134 ////
135
136 CAAudioDeviceListModel* CAAudioDeviceListModel::pModel = NULL;
137
138 CAAudioDeviceListModel* CAAudioDeviceListModel::GetModel() {
139 if(pModel == NULL) {
140 pModel = new CAAudioDeviceListModel();
141 pModel->RescanDevices();
142 pModel->InstallListeners();
143 }
144 return pModel;
145 }
146
147 OSStatus CAAudioDeviceListModel::AudioHardwarePropertyListenerCallback (
148 AudioHardwarePropertyID inPropertyID, void* inClientData
149 ) {
150 CAAudioDeviceListModel* model = CAAudioDeviceListModel::GetModel();
151 switch(inPropertyID) {
152 case kAudioHardwarePropertyDevices:
153 model->RescanDevices();
154 break;
155 case kAudioHardwarePropertyDefaultOutputDevice:
156 model->UpdateDefaultOutputDevice();
157 model->FireDefaultOutputDeviceChangedEvent(model->GetDefaultOutputDeviceID());
158 break;
159 }
160 return noErr;
161 }
162
163 OSStatus CAAudioDeviceListModel::AudioDevicePropertyListenerCallback (
164 AudioDeviceID inDevice,
165 UInt32 inChannel,
166 Boolean isInput,
167 AudioDevicePropertyID inPropertyID,
168 void* inClientData
169 ) {
170 CAAudioDeviceListModel* model = CAAudioDeviceListModel::GetModel();
171
172 switch(inPropertyID) {
173 case kAudioDevicePropertyDeviceHasChanged:
174 model->FireDeviceChangedEvent(inDevice);
175 break;
176 }
177
178 return noErr;
179 }
180
181 CAAudioDeviceListModel::CAAudioDeviceListModel() {
182 DefaultOutputDeviceID = 0;
183 }
184
185 CAAudioDeviceListModel::~CAAudioDeviceListModel() {
186 UninstallListeners();
187 }
188
189 void CAAudioDeviceListModel::InstallListeners() {
190 InstallHardwareListeners();
191 InstallDeviceListeners();
192 }
193
194 void CAAudioDeviceListModel::UninstallListeners() {
195 UninstallHardwareListeners();
196 UninstallDeviceListeners();
197 }
198
199 void CAAudioDeviceListModel::InstallHardwareListeners() {
200 // Notify when device is added or removed
201 InstallHardwareListener(kAudioHardwarePropertyDevices);
202 //Notify when the default audio output device is changed
203 InstallHardwareListener(kAudioHardwarePropertyDefaultOutputDevice);
204 }
205
206 void CAAudioDeviceListModel::UninstallHardwareListeners() {
207 UninstallHardwareListener(kAudioHardwarePropertyDevices);
208 UninstallHardwareListener(kAudioHardwarePropertyDefaultOutputDevice);
209 }
210
211 void CAAudioDeviceListModel::InstallHardwareListener(AudioHardwarePropertyID id) {
212 AudioHardwareAddPropertyListener (
213 id, AudioHardwarePropertyListenerCallback, NULL
214 );
215 }
216
217 void CAAudioDeviceListModel::UninstallHardwareListener(AudioHardwarePropertyID id) {
218 AudioHardwareRemovePropertyListener (
219 id, AudioHardwarePropertyListenerCallback
220 );
221 }
222
223 void CAAudioDeviceListModel::InstallDeviceListeners() {
224 InstallDeviceListener(kAudioDevicePropertyDeviceHasChanged);
225 }
226
227 void CAAudioDeviceListModel::UninstallDeviceListeners() {
228 UninstallDeviceListener(kAudioDevicePropertyDeviceHasChanged);
229 }
230
231 void CAAudioDeviceListModel::InstallDeviceListener(AudioDevicePropertyID id) {
232 for(int i = 0; i < GetModel()->GetOutputDeviceCount(); i++) {
233 AudioDeviceAddPropertyListener (
234 GetModel()->GetOutputDevice(i).GetID(), 0, false,
235 id, AudioDevicePropertyListenerCallback, NULL
236 );
237 }
238 }
239
240 void CAAudioDeviceListModel::UninstallDeviceListener(AudioDevicePropertyID id) {
241 for(int i = 0; i < GetModel()->GetOutputDeviceCount(); i++) {
242 AudioDeviceRemovePropertyListener (
243 GetModel()->GetOutputDevice(i).GetID(), 0, false,
244 id, AudioDevicePropertyListenerCallback
245 );
246 }
247 }
248
249 void CAAudioDeviceListModel::FireDeviceChangedEvent(AudioDeviceID devID) {
250 DeviceMutex.Lock();
251 for(int i = 0; i < GetListenerCount(); i++) {
252 GetListener(i)->DeviceChanged(devID);
253 }
254 DeviceMutex.Unlock();
255 }
256
257 void CAAudioDeviceListModel::FireDeviceListChangedEvent() {
258 DeviceMutex.Lock();
259 for(int i = 0; i < GetListenerCount(); i++) {
260 GetListener(i)->DeviceListChanged();
261 }
262 DeviceMutex.Unlock();
263 }
264
265 void CAAudioDeviceListModel::FireDefaultOutputDeviceChangedEvent(AudioDeviceID newID) {
266 DeviceMutex.Lock();
267 for(int i = 0; i < GetListenerCount(); i++) {
268 GetListener(i)->DefaultOutputDeviceChanged(newID);
269 }
270 DeviceMutex.Unlock();
271 }
272
273 AudioDeviceID CAAudioDeviceListModel::GetDefaultOutputDeviceID() {
274 return DefaultOutputDeviceID;
275 }
276
277 UInt32 CAAudioDeviceListModel::GetOutputDeviceCount() {
278 DeviceMutex.Lock();
279 int size = outDevices.size();
280 DeviceMutex.Unlock();
281 return size;
282 }
283
284 CAAudioDeviceModel CAAudioDeviceListModel::GetOutputDevice(UInt32 Index) {
285 DeviceMutex.Lock();
286 if(Index < 0 || Index >= GetOutputDeviceCount()) {
287 DeviceMutex.Unlock();
288 throw Exception("Device index out of bounds");
289 }
290
291 CAAudioDeviceModel dev = outDevices[Index];
292 DeviceMutex.Unlock();
293 return dev;
294 }
295
296 CAAudioDeviceModel CAAudioDeviceListModel::GetOutputDeviceByID(AudioDeviceID devID) {
297 DeviceMutex.Lock();
298 for(int i = 0; i < outDevices.size(); i++) {
299 if(outDevices[i].GetID() == devID) {
300 CAAudioDeviceModel dev = outDevices[i];
301 DeviceMutex.Unlock();
302 return dev;
303 }
304 }
305 DeviceMutex.Unlock();
306 throw Exception("Unknown audio device ID: " + ToString(devID));
307 }
308
309 UInt32 CAAudioDeviceListModel::GetOutputDeviceIndex(AudioDeviceID devID) {
310 DeviceMutex.Lock();
311 for(UInt32 i = 0; i < outDevices.size(); i++) {
312 if(outDevices[i].GetID() == devID) {
313 DeviceMutex.Unlock();
314 return i;
315 }
316 }
317 DeviceMutex.Unlock();
318 throw Exception("Unknown audio device ID: " + ToString(devID));
319 }
320
321 void CAAudioDeviceListModel::RescanDevices() {
322 DeviceMutex.Lock();
323 inDevices.clear();
324 outDevices.clear();
325
326 UInt32 outSize;
327 Boolean outWritable;
328
329 UpdateDefaultOutputDevice();
330
331 OSStatus res = AudioHardwareGetPropertyInfo (
332 kAudioHardwarePropertyDevices, &outSize, &outWritable
333 );
334
335 if(res) {
336 std::cerr << "Failed to get device list: " << res << std::endl;
337 DeviceMutex.Unlock();
338 return;
339 }
340
341 UInt32 deviceNumber = outSize / sizeof(AudioDeviceID);
342 if(deviceNumber < 1) {
343 std::cerr << "No audio devices found" << std::endl;
344 DeviceMutex.Unlock();
345 return;
346 }
347
348 if(deviceNumber * sizeof(AudioDeviceID) != outSize) {
349 std::cerr << "Invalid device size. This is a bug!" << std::endl;
350 DeviceMutex.Unlock();
351 return;
352 }
353
354 AudioDeviceID* devs = new AudioDeviceID[deviceNumber];
355
356 res = AudioHardwareGetProperty (
357 kAudioHardwarePropertyDevices, &outSize, devs
358 );
359
360 if(res) {
361 std::cerr << "Failed to get device IDs: " << res << std::endl;
362 delete [] devs;
363 DeviceMutex.Unlock();
364 return;
365 }
366
367 for(int i = 0; i < deviceNumber; i++) {
368 // TODO: for now skip devices which are not alive
369 outSize = sizeof(UInt32);
370 UInt32 isAlive = 0;
371
372 res = AudioDeviceGetProperty (
373 devs[i], 0, false,
374 kAudioDevicePropertyDeviceIsAlive,
375 &outSize, &isAlive
376 );
377
378 if(res || !isAlive) continue;
379 ///////
380
381 CAAudioDeviceModel dev(devs[i]);
382
383 CFStringRef tempStringRef = NULL;
384
385 // Get the name of the device
386 outSize = sizeof(CFStringRef);
387
388 res = AudioDeviceGetProperty (
389 devs[i], 0, false,
390 kAudioObjectPropertyName,
391 &outSize, &tempStringRef
392 );
393
394 dev.SetName(tempStringRef);
395 if(tempStringRef != NULL) CFRelease(tempStringRef);
396 ///////
397
398 // Get the name of the device
399 outSize = sizeof(CFStringRef);
400
401 res = AudioDeviceGetProperty (
402 devs[i], 0, false,
403 kAudioDevicePropertyDeviceUID,
404 &outSize, &tempStringRef
405 );
406
407 dev.SetUID(tempStringRef);
408 if(tempStringRef != NULL) CFRelease(tempStringRef);
409 ///////
410
411 GetChannels(&dev);
412 GetSamplerates(&dev);
413 if(dev.GetChannelNumber() > 0) outDevices.push_back(dev);
414 }
415
416 delete [] devs;
417 FireDeviceListChangedEvent();
418
419 /*for(int i = 0; i < GetOutputDeviceCount(); i++) {
420 std::cout << "Device ID: " << GetOutputDevice(i).GetID() << std::endl;
421 std::cout << "Device name: " << GetOutputDevice(i).GetName() << std::endl;
422 std::cout << "Device UID: " << GetOutputDevice(i).GetUID() << std::endl;
423 std::cout << "Channels: " << GetOutputDevice(i).GetChannelNumber() << std::endl;
424 std::cout << "Default samplerate: " << GetOutputDevice(i).GetDefaultSamplerate() << std::endl;
425
426 const std::vector<int> rates = GetOutputDevice(i).GetNominalSamplerates();
427 std::cout << "Nominal samplerates: " << std::endl;
428 for(int j = 0; j < rates.size(); j++) {
429 std::cout << "\t" << rates[j] << std::endl;
430 }
431 std::cout << std::endl;
432 }*/
433 DeviceMutex.Unlock();
434 }
435
436 void CAAudioDeviceListModel::UpdateDefaultOutputDevice() {
437 AudioDeviceID id;
438 UInt32 size = sizeof(AudioDeviceID);
439 OSStatus res = AudioHardwareGetProperty (
440 kAudioHardwarePropertyDefaultOutputDevice, &size, &id
441 );
442 if(res) std::cerr << "Failed to get default output device: " << res << std::endl;
443 else DefaultOutputDeviceID = id;
444 }
445
446 void CAAudioDeviceListModel::GetChannels(CAAudioDeviceModel* pDev) {
447 UInt32 outSize;
448 bool isInput = false;
449
450 OSStatus res = AudioDeviceGetPropertyInfo (
451 pDev->GetID(), 0, isInput,
452 kAudioDevicePropertyStreamConfiguration,
453 &outSize, NULL
454 );
455 if(res || outSize == 0) {
456 if(res) std::cerr << "Failed to get stream config: " << res << std::endl;
457 return;
458 }
459
460 AudioBufferList* pBufferList = NULL;
461 pBufferList = (AudioBufferList*)malloc(outSize);
462 if(pBufferList == NULL) {
463 perror(NULL);
464 return;
465 }
466
467 res = AudioDeviceGetProperty (
468 pDev->GetID(), 0, isInput,
469 kAudioDevicePropertyStreamConfiguration,
470 &outSize, pBufferList
471 );
472
473 if(res = noErr) {
474 std::cerr << "Failed to get channel number: " << res << std::endl;
475 free(pBufferList);
476 return;
477 }
478
479 UInt32 chns = 0;
480 for(int i = 0; i < pBufferList->mNumberBuffers; i++) {
481 chns += pBufferList->mBuffers[i].mNumberChannels;
482 }
483
484 pDev->ChannelNumber = chns;
485
486 free(pBufferList);
487 }
488
489 /*void CAAudioDeviceListModel::GetStreams(CAAudioDeviceModel* pDev) {
490 UInt32 outSize = sizeof(AudioStreamID);
491
492 OSStatus res = AudioDeviceGetPropertyInfo (
493 pDev->GetID(), 0, false,
494 kAudioDevicePropertyStreams,
495 &outSize, NULL
496 );
497
498 if(res) {
499 std::cerr << "Failed to get device streams: " << res << std::endl;
500 return;
501 }
502
503 UInt32 streamNumber = outSize / sizeof(AudioStreamID);
504 if(streamNumber < 1) {
505 std::cerr << "No streams found" << std::endl;
506 return;
507 }
508
509 if(streamNumber * sizeof(AudioStreamID) != outSize) {
510 std::cerr << "Invalid AudioStreamID size. This is a bug!" << std::endl;
511 return;
512 }
513
514 AudioStreamID* streams = new AudioStreamID[streamNumber];
515
516 res = AudioDeviceGetProperty (
517 pDev->GetID(), 0, false,
518 kAudioDevicePropertyStreams,
519 &outSize, streams
520 );
521
522 if(res) {
523 std::cerr << "Failed to get stream IDs: " << res << std::endl;
524 delete [] streams;
525 return;
526 }
527
528 for(int i = 0; i < streamNumber; i++) {
529 UInt32 inStream;
530
531 res = AudioStreamGetProperty (
532 streams[i], 0, kAudioStreamPropertyDirection, &outSize, &inStream
533 );
534
535 if(res) {
536 std::cerr << "Failed to get stream direction: " << res << std::endl;
537 continue;
538 }
539
540 //pDev->AudioStreams.push_back(CAAudioStream(inStream, chns));
541 }
542
543 delete [] streams;
544 }*/
545
546 void CAAudioDeviceListModel::GetSamplerates(CAAudioDeviceModel* pDev) {
547 UInt32 outSize;
548
549 // Get current nominal sample rate
550 outSize = sizeof(Float64);
551 Float64 srate;
552
553 OSStatus res = AudioDeviceGetProperty (
554 pDev->GetID(), 0, false,
555 kAudioDevicePropertyNominalSampleRate,
556 &outSize, &srate
557 );
558
559 if(res) std::cerr << "Failed to get default samplerate: " << res << std::endl;
560 else pDev->DefaultSamplerate = srate;
561 ///////
562
563 res = AudioDeviceGetPropertyInfo (
564 pDev->GetID(), 0, false,
565 kAudioDevicePropertyAvailableNominalSampleRates,
566 &outSize, NULL
567 );
568
569 if(res) {
570 std::cerr << "Failed to get nominal samplerates: " << res << std::endl;
571 return;
572 }
573
574 UInt32 rangeNumber = outSize / sizeof(AudioValueRange);
575 if(rangeNumber < 1) {
576 std::cerr << "No nominal samplerates found" << std::endl;
577 return;
578 }
579
580 if(rangeNumber * sizeof(AudioValueRange) != outSize) {
581 std::cerr << "Invalid AudioValueRange size. This is a bug!" << std::endl;
582 return;
583 }
584
585 AudioValueRange* ranges = new AudioValueRange[rangeNumber];
586
587 res = AudioDeviceGetProperty (
588 pDev->GetID(), 0, false,
589 kAudioDevicePropertyAvailableNominalSampleRates,
590 &outSize, ranges
591 );
592
593 if(res) {
594 std::cerr << "Failed to get samplerate ranges: " << res << std::endl;
595 delete [] ranges;
596 return;
597 }
598
599 for(int i = 0; i < rangeNumber; i++) {
600 // FIXME: might be ranges of valid samplerates
601 UInt32 min = (UInt32)ranges[i].mMinimum;
602 UInt32 max = (UInt32)ranges[i].mMaximum;
603 pDev->NominalSamplerates.push_back(min);
604 if(min != max) pDev->NominalSamplerates.push_back(max);
605 }
606
607 delete [] ranges;
608 }
609 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC