f68d41f6a1c6126a602d8dcf0b3dc8329fc244aa
[blender.git] / intern / audaspace / OpenAL / AUD_OpenALDevice.cpp
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * Copyright 2009-2011 Jörg Hermann Müller
5  *
6  * This file is part of AudaSpace.
7  *
8  * Audaspace is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * AudaSpace is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with Audaspace; if not, write to the Free Software Foundation,
20  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21  *
22  * ***** END GPL LICENSE BLOCK *****
23  */
24
25 /** \file audaspace/OpenAL/AUD_OpenALDevice.cpp
26  *  \ingroup audopenal
27  */
28
29
30 #include "AUD_OpenALDevice.h"
31 #include "AUD_IFactory.h"
32 #include "AUD_IReader.h"
33 #include "AUD_ConverterReader.h"
34
35 #include <cstring>
36 #include <limits>
37
38 #ifdef WIN32
39 #include <windows.h>
40 #else
41 #include <unistd.h>
42 #endif
43
44 /*struct AUD_OpenALBufferedFactory
45 {
46         /// The factory.
47         AUD_IFactory* factory;
48
49         /// The OpenAL buffer.
50         ALuint buffer;
51 };*/
52
53 //typedef std::list<AUD_OpenALBufferedFactory*>::iterator AUD_BFIterator;
54
55
56 /******************************************************************************/
57 /*********************** AUD_OpenALHandle Handle Code *************************/
58 /******************************************************************************/
59
60 static const char* genbuffer_error = "AUD_OpenALDevice: Buffer couldn't be "
61                                                                          "generated.";
62 static const char* gensource_error = "AUD_OpenALDevice: Source couldn't be "
63                                                                          "generated.";
64 static const char* queue_error = "AUD_OpenALDevice: Buffer couldn't be "
65                                                                  "queued to the source.";
66 static const char* bufferdata_error = "AUD_OpenALDevice: Buffer couldn't be "
67                                                                           "filled with data.";
68
69 AUD_OpenALDevice::AUD_OpenALHandle::AUD_OpenALHandle(AUD_OpenALDevice* device, ALenum format, AUD_Reference<AUD_IReader> reader, bool keep) :
70         m_isBuffered(false), m_reader(reader), m_keep(keep), m_format(format), m_current(0),
71         m_eos(false), m_loopcount(0), m_stop(NULL), m_stop_data(NULL), m_status(AUD_STATUS_PLAYING),
72         m_device(device)
73 {
74         AUD_DeviceSpecs specs = m_device->m_specs;
75         specs.specs = m_reader->getSpecs();
76
77         // OpenAL playback code
78         alGenBuffers(CYCLE_BUFFERS, m_buffers);
79         if(alGetError() != AL_NO_ERROR)
80                 AUD_THROW(AUD_ERROR_OPENAL, genbuffer_error);
81
82         try
83         {
84                 m_device->m_buffer.assureSize(m_device->m_buffersize * AUD_DEVICE_SAMPLE_SIZE(specs));
85                 int length;
86                 bool eos;
87
88                 for(int i = 0; i < CYCLE_BUFFERS; i++)
89                 {
90                         length = m_device->m_buffersize;
91                         reader->read(length, eos, m_device->m_buffer.getBuffer());
92                         alBufferData(m_buffers[i], m_format, m_device->m_buffer.getBuffer(),
93                                                  length * AUD_DEVICE_SAMPLE_SIZE(specs),
94                                                  specs.rate);
95                         if(alGetError() != AL_NO_ERROR)
96                                 AUD_THROW(AUD_ERROR_OPENAL, bufferdata_error);
97                 }
98
99                 alGenSources(1, &m_source);
100                 if(alGetError() != AL_NO_ERROR)
101                         AUD_THROW(AUD_ERROR_OPENAL, gensource_error);
102
103                 try
104                 {
105                         alSourceQueueBuffers(m_source, CYCLE_BUFFERS,
106                                                                  m_buffers);
107                         if(alGetError() != AL_NO_ERROR)
108                                 AUD_THROW(AUD_ERROR_OPENAL, queue_error);
109                 }
110                 catch(AUD_Exception&)
111                 {
112                         alDeleteSources(1, &m_source);
113                         throw;
114                 }
115         }
116         catch(AUD_Exception&)
117         {
118                 alDeleteBuffers(CYCLE_BUFFERS, m_buffers);
119                 throw;
120         }
121         alSourcei(m_source, AL_SOURCE_RELATIVE, 1);
122 }
123
124 bool AUD_OpenALDevice::AUD_OpenALHandle::pause()
125 {
126         if(m_status)
127         {
128                 m_device->lock();
129
130                 if(m_status == AUD_STATUS_PLAYING)
131                 {
132                         m_device->m_playingSounds.remove(this);
133                         m_device->m_pausedSounds.push_back(this);
134
135                         alSourcePause(m_source);
136
137                         m_status = AUD_STATUS_PAUSED;
138                         m_device->unlock();
139
140                         return true;
141                 }
142
143                 m_device->unlock();
144         }
145
146         return false;
147 }
148
149 bool AUD_OpenALDevice::AUD_OpenALHandle::resume()
150 {
151         if(m_status)
152         {
153                 m_device->lock();
154
155                 if(m_status == AUD_STATUS_PAUSED)
156                 {
157                         m_device->m_pausedSounds.remove(this);
158                         m_device->m_playingSounds.push_back(this);
159
160                         m_device->start();
161                         m_status = AUD_STATUS_PLAYING;
162                         m_device->unlock();
163                         return true;
164                 }
165
166                 m_device->unlock();
167         }
168
169         return false;
170 }
171
172 bool AUD_OpenALDevice::AUD_OpenALHandle::stop()
173 {
174         if(!m_status)
175                 return false;
176
177         m_device->lock();
178
179         // AUD_XXX Create a reference of our own object so that it doesn't get
180         // deleted before the end of this function
181         AUD_Reference<AUD_OpenALHandle> This = this;
182
183         if(m_status == AUD_STATUS_PLAYING)
184                 m_device->m_playingSounds.remove(This);
185         else
186                 m_device->m_pausedSounds.remove(This);
187
188         m_device->unlock();
189
190         alDeleteSources(1, &m_source);
191         if(!m_isBuffered)
192                 alDeleteBuffers(CYCLE_BUFFERS, m_buffers);
193
194         m_status = AUD_STATUS_INVALID;
195         return true;
196 }
197
198 bool AUD_OpenALDevice::AUD_OpenALHandle::getKeep()
199 {
200         if(m_status)
201                 return m_keep;
202
203         return false;
204 }
205
206 bool AUD_OpenALDevice::AUD_OpenALHandle::setKeep(bool keep)
207 {
208         if(!m_status)
209                 return false;
210
211         m_device->lock();
212
213         m_keep = keep;
214
215         m_device->unlock();
216
217         return true;
218 }
219
220 bool AUD_OpenALDevice::AUD_OpenALHandle::seek(float position)
221 {
222         if(!m_status)
223                 return false;
224
225         m_device->lock();
226
227         if(m_isBuffered)
228                 alSourcef(m_source, AL_SEC_OFFSET, position);
229         else
230         {
231                 m_reader->seek((int)(position * m_reader->getSpecs().rate));
232                 m_eos = false;
233
234                 ALint info;
235
236                 alGetSourcei(m_source, AL_SOURCE_STATE, &info);
237
238                 if(info != AL_PLAYING)
239                 {
240                         if(info == AL_PAUSED)
241                                 alSourceStop(m_source);
242
243                         alSourcei(m_source, AL_BUFFER, 0);
244                         m_current = 0;
245
246                         ALenum err;
247                         if((err = alGetError()) == AL_NO_ERROR)
248                         {
249                                 int length;
250                                 AUD_DeviceSpecs specs = m_device->m_specs;
251                                 specs.specs = m_reader->getSpecs();
252                                 m_device->m_buffer.assureSize(m_device->m_buffersize * AUD_DEVICE_SAMPLE_SIZE(specs));
253
254                                 for(int i = 0; i < CYCLE_BUFFERS; i++)
255                                 {
256                                         length = m_device->m_buffersize;
257                                         m_reader->read(length, m_eos, m_device->m_buffer.getBuffer());
258                                         alBufferData(m_buffers[i], m_format, m_device->m_buffer.getBuffer(),
259                                                                  length * AUD_DEVICE_SAMPLE_SIZE(specs), specs.rate);
260
261                                         if(alGetError() != AL_NO_ERROR)
262                                                 break;
263                                 }
264
265                                 if(m_loopcount != 0)
266                                         m_eos = false;
267
268                                 alSourceQueueBuffers(m_source, CYCLE_BUFFERS, m_buffers);
269                         }
270
271                         alSourceRewind(m_source);
272                 }
273         }
274
275         m_device->unlock();
276
277         return true;
278 }
279
280 float AUD_OpenALDevice::AUD_OpenALHandle::getPosition()
281 {
282         if(!m_status)
283                 return 0.0f;
284
285         m_device->lock();
286
287         float position = 0.0f;
288
289         alGetSourcef(m_source, AL_SEC_OFFSET, &position);
290
291         if(!m_isBuffered)
292         {
293                 AUD_Specs specs = m_reader->getSpecs();
294                 position += (m_reader->getPosition() - m_device->m_buffersize *
295                                          CYCLE_BUFFERS) / (float)specs.rate;
296         }
297
298         m_device->unlock();
299
300         return position;
301 }
302
303 AUD_Status AUD_OpenALDevice::AUD_OpenALHandle::getStatus()
304 {
305         return m_status;
306 }
307
308 float AUD_OpenALDevice::AUD_OpenALHandle::getVolume()
309 {
310         float result = std::numeric_limits<float>::quiet_NaN();
311
312         if(!m_status)
313                 return result;
314
315         m_device->lock();
316
317         alGetSourcef(m_source, AL_GAIN, &result);
318
319         m_device->unlock();
320
321         return result;
322 }
323
324 bool AUD_OpenALDevice::AUD_OpenALHandle::setVolume(float volume)
325 {
326         if(!m_status)
327                 return false;
328
329         m_device->lock();
330
331         alSourcef(m_source, AL_GAIN, volume);
332
333         m_device->unlock();
334
335         return true;
336 }
337
338 float AUD_OpenALDevice::AUD_OpenALHandle::getPitch()
339 {
340         float result = std::numeric_limits<float>::quiet_NaN();
341
342         if(!m_status)
343                 return result;
344
345         m_device->lock();
346
347         alGetSourcef(m_source, AL_PITCH, &result);
348
349         m_device->unlock();
350
351         return result;
352 }
353
354 bool AUD_OpenALDevice::AUD_OpenALHandle::setPitch(float pitch)
355 {
356         if(!m_status)
357                 return false;
358
359         m_device->lock();
360
361         alSourcef(m_source, AL_PITCH, pitch);
362
363         m_device->unlock();
364
365         return true;
366 }
367
368 int AUD_OpenALDevice::AUD_OpenALHandle::getLoopCount()
369 {
370         if(!m_status)
371                 return 0;
372         return m_loopcount;
373 }
374
375 bool AUD_OpenALDevice::AUD_OpenALHandle::setLoopCount(int count)
376 {
377         if(!m_status)
378                 return false;
379         m_loopcount = count;
380         return true;
381 }
382
383 bool AUD_OpenALDevice::AUD_OpenALHandle::setStopCallback(stopCallback callback, void* data)
384 {
385         if(!m_status)
386                 return false;
387
388         m_device->lock();
389
390         m_stop = callback;
391         m_stop_data = data;
392
393         m_device->unlock();
394
395         return true;
396 }
397
398 /******************************************************************************/
399 /********************* AUD_OpenALHandle 3DHandle Code *************************/
400 /******************************************************************************/
401
402 AUD_Vector3 AUD_OpenALDevice::AUD_OpenALHandle::getSourceLocation()
403 {
404         AUD_Vector3 result = AUD_Vector3(0, 0, 0);
405
406         if(!m_status)
407                 return result;
408
409         m_device->lock();
410
411         ALfloat p[3];
412         alGetSourcefv(m_source, AL_POSITION, p);
413
414         m_device->unlock();
415
416         result = AUD_Vector3(p[0], p[1], p[2]);
417
418         return result;
419 }
420
421 bool AUD_OpenALDevice::AUD_OpenALHandle::setSourceLocation(const AUD_Vector3& location)
422 {
423         if(!m_status)
424                 return false;
425
426         m_device->lock();
427
428         alSourcefv(m_source, AL_POSITION, (ALfloat*)location.get());
429
430         m_device->unlock();
431
432         return true;
433 }
434
435 AUD_Vector3 AUD_OpenALDevice::AUD_OpenALHandle::getSourceVelocity()
436 {
437         AUD_Vector3 result = AUD_Vector3(0, 0, 0);
438
439         if(!m_status)
440                 return result;
441
442         m_device->lock();
443
444         ALfloat v[3];
445         alGetSourcefv(m_source, AL_VELOCITY, v);
446
447         m_device->unlock();
448
449         result = AUD_Vector3(v[0], v[1], v[2]);
450
451         return result;
452 }
453
454 bool AUD_OpenALDevice::AUD_OpenALHandle::setSourceVelocity(const AUD_Vector3& velocity)
455 {
456         if(!m_status)
457                 return false;
458
459         m_device->lock();
460
461         alSourcefv(m_source, AL_VELOCITY, (ALfloat*)velocity.get());
462
463         m_device->unlock();
464
465         return true;
466 }
467
468 AUD_Quaternion AUD_OpenALDevice::AUD_OpenALHandle::getSourceOrientation()
469 {
470         return m_orientation;
471 }
472
473 bool AUD_OpenALDevice::AUD_OpenALHandle::setSourceOrientation(const AUD_Quaternion& orientation)
474 {
475         if(!m_status)
476                 return false;
477
478         ALfloat direction[3];
479         direction[0] = -2 * (orientation.w() * orientation.y() +
480                                                  orientation.x() * orientation.z());
481         direction[1] = 2 * (orientation.x() * orientation.w() -
482                                                 orientation.z() * orientation.y());
483         direction[2] = 2 * (orientation.x() * orientation.x() +
484                                                 orientation.y() * orientation.y()) - 1;
485         m_device->lock();
486
487         alSourcefv(m_source, AL_DIRECTION, direction);
488
489         m_device->unlock();
490
491         m_orientation = orientation;
492
493         return true;
494 }
495
496 bool AUD_OpenALDevice::AUD_OpenALHandle::isRelative()
497 {
498         int result;
499
500         if(!m_status)
501                 return false;
502
503         m_device->lock();
504
505         alGetSourcei(m_source, AL_SOURCE_RELATIVE, &result);
506
507         m_device->unlock();
508
509         return result;
510 }
511
512 bool AUD_OpenALDevice::AUD_OpenALHandle::setRelative(bool relative)
513 {
514         if(!m_status)
515                 return false;
516
517         m_device->lock();
518
519         alSourcei(m_source, AL_SOURCE_RELATIVE, relative);
520
521         m_device->unlock();
522
523         return true;
524 }
525
526 float AUD_OpenALDevice::AUD_OpenALHandle::getVolumeMaximum()
527 {
528         float result = std::numeric_limits<float>::quiet_NaN();
529
530         if(!m_status)
531                 return result;
532
533         m_device->lock();
534
535         alGetSourcef(m_source, AL_MAX_GAIN, &result);
536
537         m_device->unlock();
538
539         return result;
540 }
541
542 bool AUD_OpenALDevice::AUD_OpenALHandle::setVolumeMaximum(float volume)
543 {
544         if(!m_status)
545                 return false;
546
547         m_device->lock();
548
549         alSourcef(m_source, AL_MAX_GAIN, volume);
550
551         m_device->unlock();
552
553         return true;
554 }
555
556 float AUD_OpenALDevice::AUD_OpenALHandle::getVolumeMinimum()
557 {
558         float result = std::numeric_limits<float>::quiet_NaN();
559
560         if(!m_status)
561                 return result;
562
563         m_device->lock();
564
565         alGetSourcef(m_source, AL_MIN_GAIN, &result);
566
567         m_device->unlock();
568
569         return result;
570 }
571
572 bool AUD_OpenALDevice::AUD_OpenALHandle::setVolumeMinimum(float volume)
573 {
574         if(!m_status)
575                 return false;
576
577         m_device->lock();
578
579         alSourcef(m_source, AL_MIN_GAIN, volume);
580
581         m_device->unlock();
582
583         return true;
584 }
585
586 float AUD_OpenALDevice::AUD_OpenALHandle::getDistanceMaximum()
587 {
588         float result = std::numeric_limits<float>::quiet_NaN();
589
590         if(!m_status)
591                 return result;
592
593         m_device->lock();
594
595         alGetSourcef(m_source, AL_MAX_DISTANCE, &result);
596
597         m_device->unlock();
598
599         return result;
600 }
601
602 bool AUD_OpenALDevice::AUD_OpenALHandle::setDistanceMaximum(float distance)
603 {
604         if(!m_status)
605                 return false;
606
607         m_device->lock();
608
609         alSourcef(m_source, AL_MAX_DISTANCE, distance);
610
611         m_device->unlock();
612
613         return true;
614 }
615
616 float AUD_OpenALDevice::AUD_OpenALHandle::getDistanceReference()
617 {
618         float result = std::numeric_limits<float>::quiet_NaN();
619
620         if(!m_status)
621                 return result;
622
623         m_device->lock();
624
625         alGetSourcef(m_source, AL_REFERENCE_DISTANCE, &result);
626
627         m_device->unlock();
628
629         return result;
630 }
631
632 bool AUD_OpenALDevice::AUD_OpenALHandle::setDistanceReference(float distance)
633 {
634         if(!m_status)
635                 return false;
636
637         m_device->lock();
638
639         alSourcef(m_source, AL_REFERENCE_DISTANCE, distance);
640
641         m_device->unlock();
642
643         return true;
644 }
645
646 float AUD_OpenALDevice::AUD_OpenALHandle::getAttenuation()
647 {
648         float result = std::numeric_limits<float>::quiet_NaN();
649
650         if(!m_status)
651                 return result;
652
653         m_device->lock();
654
655         alGetSourcef(m_source, AL_ROLLOFF_FACTOR, &result);
656
657         m_device->unlock();
658
659         return result;
660 }
661
662 bool AUD_OpenALDevice::AUD_OpenALHandle::setAttenuation(float factor)
663 {
664         if(!m_status)
665                 return false;
666
667         m_device->lock();
668
669         alSourcef(m_source, AL_ROLLOFF_FACTOR, factor);
670
671         m_device->unlock();
672
673         return true;
674 }
675
676 float AUD_OpenALDevice::AUD_OpenALHandle::getConeAngleOuter()
677 {
678         float result = std::numeric_limits<float>::quiet_NaN();
679
680         if(!m_status)
681                 return result;
682
683         m_device->lock();
684
685         alGetSourcef(m_source, AL_CONE_OUTER_ANGLE, &result);
686
687         m_device->unlock();
688
689         return result;
690 }
691
692 bool AUD_OpenALDevice::AUD_OpenALHandle::setConeAngleOuter(float angle)
693 {
694         if(!m_status)
695                 return false;
696
697         m_device->lock();
698
699         alSourcef(m_source, AL_CONE_OUTER_ANGLE, angle);
700
701         m_device->unlock();
702
703         return true;
704 }
705
706 float AUD_OpenALDevice::AUD_OpenALHandle::getConeAngleInner()
707 {
708         float result = std::numeric_limits<float>::quiet_NaN();
709
710         if(!m_status)
711                 return result;
712
713         m_device->lock();
714
715         alGetSourcef(m_source, AL_CONE_INNER_ANGLE, &result);
716
717         m_device->unlock();
718
719         return result;
720 }
721
722 bool AUD_OpenALDevice::AUD_OpenALHandle::setConeAngleInner(float angle)
723 {
724         if(!m_status)
725                 return false;
726
727         m_device->lock();
728
729         alSourcef(m_source, AL_CONE_INNER_ANGLE, angle);
730
731         m_device->unlock();
732
733         return true;
734 }
735
736 float AUD_OpenALDevice::AUD_OpenALHandle::getConeVolumeOuter()
737 {
738         float result = std::numeric_limits<float>::quiet_NaN();
739
740         if(!m_status)
741                 return result;
742
743         m_device->lock();
744
745         alGetSourcef(m_source, AL_CONE_OUTER_GAIN, &result);
746
747         m_device->unlock();
748
749         return result;
750 }
751
752 bool AUD_OpenALDevice::AUD_OpenALHandle::setConeVolumeOuter(float volume)
753 {
754         if(!m_status)
755                 return false;
756
757         m_device->lock();
758
759         alSourcef(m_source, AL_CONE_OUTER_GAIN, volume);
760
761         m_device->unlock();
762
763         return true;
764 }
765
766 /******************************************************************************/
767 /**************************** Threading Code **********************************/
768 /******************************************************************************/
769
770 static void *AUD_openalRunThread(void *device)
771 {
772         AUD_OpenALDevice* dev = (AUD_OpenALDevice*)device;
773         dev->updateStreams();
774         return NULL;
775 }
776
777 void AUD_OpenALDevice::start(bool join)
778 {
779         lock();
780
781         if(!m_playing)
782         {
783                 if(join)
784                         pthread_join(m_thread, NULL);
785
786                 pthread_attr_t attr;
787                 pthread_attr_init(&attr);
788                 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
789
790                 pthread_create(&m_thread, &attr, AUD_openalRunThread, this);
791
792                 pthread_attr_destroy(&attr);
793
794                 m_playing = true;
795         }
796
797         unlock();
798 }
799
800 void AUD_OpenALDevice::updateStreams()
801 {
802         AUD_Reference<AUD_OpenALHandle> sound;
803
804         int length;
805
806         ALint info;
807         AUD_DeviceSpecs specs = m_specs;
808         ALCenum cerr;
809         std::list<AUD_Reference<AUD_OpenALHandle> > stopSounds;
810         std::list<AUD_Reference<AUD_OpenALHandle> > pauseSounds;
811         AUD_HandleIterator it;
812
813         while(1)
814         {
815                 lock();
816
817                 alcSuspendContext(m_context);
818                 cerr = alcGetError(m_device);
819                 if(cerr == ALC_NO_ERROR)
820                 {
821                         // for all sounds
822                         for(it = m_playingSounds.begin(); it != m_playingSounds.end(); it++)
823                         {
824                                 sound = *it;
825
826                                 // is it a streamed sound?
827                                 if(!sound->m_isBuffered)
828                                 {
829                                         // check for buffer refilling
830                                         alGetSourcei(sound->m_source, AL_BUFFERS_PROCESSED, &info);
831
832                                         if(info)
833                                         {
834                                                 specs.specs = sound->m_reader->getSpecs();
835                                                 m_buffer.assureSize(m_buffersize * AUD_DEVICE_SAMPLE_SIZE(specs));
836
837                                                 // for all empty buffers
838                                                 while(info--)
839                                                 {
840                                                         // if there's still data to play back
841                                                         if(!sound->m_eos)
842                                                         {
843                                                                 // read data
844                                                                 length = m_buffersize;
845                                                                 sound->m_reader->read(length, sound->m_eos, m_buffer.getBuffer());
846
847                                                                 // looping necessary?
848                                                                 if(length == 0 && sound->m_loopcount)
849                                                                 {
850                                                                         if(sound->m_loopcount > 0)
851                                                                                 sound->m_loopcount--;
852
853                                                                         sound->m_reader->seek(0);
854
855                                                                         length = m_buffersize;
856                                                                         sound->m_reader->read(length, sound->m_eos, m_buffer.getBuffer());
857                                                                 }
858
859                                                                 if(sound->m_loopcount != 0)
860                                                                         sound->m_eos = false;
861
862                                                                 // read nothing?
863                                                                 if(length == 0)
864                                                                 {
865                                                                         break;
866                                                                 }
867
868                                                                 // unqueue buffer
869                                                                 alSourceUnqueueBuffers(sound->m_source, 1,
870                                                                                                 &sound->m_buffers[sound->m_current]);
871                                                                 ALenum err;
872                                                                 if((err = alGetError()) != AL_NO_ERROR)
873                                                                 {
874                                                                         sound->m_eos = true;
875                                                                         break;
876                                                                 }
877
878                                                                 // fill with new data
879                                                                 alBufferData(sound->m_buffers[sound->m_current],
880                                                                                          sound->m_format,
881                                                                                          m_buffer.getBuffer(), length *
882                                                                                          AUD_DEVICE_SAMPLE_SIZE(specs),
883                                                                                          specs.rate);
884
885                                                                 if((err = alGetError()) != AL_NO_ERROR)
886                                                                 {
887                                                                         sound->m_eos = true;
888                                                                         break;
889                                                                 }
890
891                                                                 // and queue again
892                                                                 alSourceQueueBuffers(sound->m_source, 1,
893                                                                                                 &sound->m_buffers[sound->m_current]);
894                                                                 if(alGetError() != AL_NO_ERROR)
895                                                                 {
896                                                                         sound->m_eos = true;
897                                                                         break;
898                                                                 }
899
900                                                                 sound->m_current = (sound->m_current+1) %
901                                                                                                  AUD_OpenALHandle::CYCLE_BUFFERS;
902                                                         }
903                                                         else
904                                                                 break;
905                                                 }
906                                         }
907                                 }
908
909                                 // check if the sound has been stopped
910                                 alGetSourcei(sound->m_source, AL_SOURCE_STATE, &info);
911
912                                 if(info != AL_PLAYING)
913                                 {
914                                         // if it really stopped
915                                         if(sound->m_eos)
916                                         {
917                                                 if(sound->m_stop)
918                                                         sound->m_stop(sound->m_stop_data);
919
920                                                 // pause or
921                                                 if(sound->m_keep)
922                                                         pauseSounds.push_back(sound);
923                                                 // stop
924                                                 else
925                                                         stopSounds.push_back(sound);
926                                         }
927                                         // continue playing
928                                         else
929                                                 alSourcePlay(sound->m_source);
930                                 }
931                         }
932
933                         for(it = pauseSounds.begin(); it != pauseSounds.end(); it++)
934                                 (*it)->pause();
935
936                         for(it = stopSounds.begin(); it != stopSounds.end(); it++)
937                                 (*it)->stop();
938
939                         pauseSounds.clear();
940                         stopSounds.clear();
941
942                         alcProcessContext(m_context);
943                 }
944
945                 // stop thread
946                 if(m_playingSounds.empty() || (cerr != ALC_NO_ERROR))
947                 {
948                         m_playing = false;
949                         unlock();
950                         pthread_exit(NULL);
951                 }
952
953                 unlock();
954
955 #ifdef WIN32
956                 Sleep(20);
957 #else
958                 usleep(20000);
959 #endif
960         }
961 }
962
963 /******************************************************************************/
964 /**************************** IDevice Code ************************************/
965 /******************************************************************************/
966
967 static const char* open_error = "AUD_OpenALDevice: Device couldn't be opened.";
968
969 AUD_OpenALDevice::AUD_OpenALDevice(AUD_DeviceSpecs specs, int buffersize)
970 {
971         // cannot determine how many channels or which format OpenAL uses, but
972         // it at least is able to play 16 bit stereo audio
973         specs.channels = AUD_CHANNELS_STEREO;
974         specs.format = AUD_FORMAT_S16;
975
976 #if 0
977         if(alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT") == AL_TRUE)
978         {
979                 ALCchar* devices = const_cast<ALCchar*>(alcGetString(NULL, ALC_DEVICE_SPECIFIER));
980                 printf("OpenAL devices (standard is: %s):\n", alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER));
981
982                 while(*devices)
983                 {
984                         printf("%s\n", devices);
985                         devices += strlen(devices) + 1;
986                 }
987         }
988 #endif
989
990         m_device = alcOpenDevice(NULL);
991
992         if(!m_device)
993                 AUD_THROW(AUD_ERROR_OPENAL, open_error);
994
995         // at least try to set the frequency
996         ALCint attribs[] = { ALC_FREQUENCY, (ALCint)specs.rate, 0 };
997         ALCint* attributes = attribs;
998         if(specs.rate == AUD_RATE_INVALID)
999                 attributes = NULL;
1000
1001         m_context = alcCreateContext(m_device, attributes);
1002         alcMakeContextCurrent(m_context);
1003
1004         alcGetIntegerv(m_device, ALC_FREQUENCY, 1, (ALCint*)&specs.rate);
1005
1006         // check for specific formats and channel counts to be played back
1007         if(alIsExtensionPresent("AL_EXT_FLOAT32") == AL_TRUE)
1008                 specs.format = AUD_FORMAT_FLOAT32;
1009
1010         m_useMC = alIsExtensionPresent("AL_EXT_MCFORMATS") == AL_TRUE;
1011
1012         alGetError();
1013         alcGetError(m_device);
1014
1015         m_specs = specs;
1016         m_buffersize = buffersize;
1017         m_playing = false;
1018
1019 //      m_bufferedFactories = new std::list<AUD_OpenALBufferedFactory*>();
1020
1021         pthread_mutexattr_t attr;
1022         pthread_mutexattr_init(&attr);
1023         pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
1024
1025         pthread_mutex_init(&m_mutex, &attr);
1026
1027         pthread_mutexattr_destroy(&attr);
1028
1029         start(false);
1030 }
1031
1032 AUD_OpenALDevice::~AUD_OpenALDevice()
1033 {
1034         lock();
1035         alcSuspendContext(m_context);
1036
1037         while(!m_playingSounds.empty())
1038                 m_playingSounds.front()->stop();
1039
1040         while(!m_pausedSounds.empty())
1041                 m_pausedSounds.front()->stop();
1042
1043
1044         // delete all buffered factories
1045         /*while(!m_bufferedFactories->empty())
1046         {
1047                 alDeleteBuffers(1, &(*(m_bufferedFactories->begin()))->buffer);
1048                 delete *m_bufferedFactories->begin();
1049                 m_bufferedFactories->erase(m_bufferedFactories->begin());
1050         }*/
1051
1052         alcProcessContext(m_context);
1053
1054         // wait for the thread to stop
1055         unlock();
1056         pthread_join(m_thread, NULL);
1057
1058         //delete m_bufferedFactories;
1059
1060         // quit OpenAL
1061         alcMakeContextCurrent(NULL);
1062         alcDestroyContext(m_context);
1063         alcCloseDevice(m_device);
1064
1065         pthread_mutex_destroy(&m_mutex);
1066 }
1067
1068 AUD_DeviceSpecs AUD_OpenALDevice::getSpecs() const
1069 {
1070         return m_specs;
1071 }
1072
1073 bool AUD_OpenALDevice::getFormat(ALenum &format, AUD_Specs specs)
1074 {
1075         bool valid = true;
1076         format = 0;
1077
1078         switch(m_specs.format)
1079         {
1080         case AUD_FORMAT_S16:
1081                 switch(specs.channels)
1082                 {
1083                 case AUD_CHANNELS_MONO:
1084                         format = AL_FORMAT_MONO16;
1085                         break;
1086                 case AUD_CHANNELS_STEREO:
1087                         format = AL_FORMAT_STEREO16;
1088                         break;
1089                 case AUD_CHANNELS_SURROUND4:
1090                         if(m_useMC)
1091                         {
1092                                 format = alGetEnumValue("AL_FORMAT_QUAD16");
1093                                 break;
1094                         }
1095                 case AUD_CHANNELS_SURROUND51:
1096                         if(m_useMC)
1097                         {
1098                                 format = alGetEnumValue("AL_FORMAT_51CHN16");
1099                                 break;
1100                         }
1101                 case AUD_CHANNELS_SURROUND61:
1102                         if(m_useMC)
1103                         {
1104                                 format = alGetEnumValue("AL_FORMAT_61CHN16");
1105                                 break;
1106                         }
1107                 case AUD_CHANNELS_SURROUND71:
1108                         if(m_useMC)
1109                         {
1110                                 format = alGetEnumValue("AL_FORMAT_71CHN16");
1111                                 break;
1112                         }
1113                 default:
1114                         valid = false;
1115                 }
1116                 break;
1117         case AUD_FORMAT_FLOAT32:
1118                 switch(specs.channels)
1119                 {
1120                 case AUD_CHANNELS_MONO:
1121                         format = alGetEnumValue("AL_FORMAT_MONO_FLOAT32");
1122                         break;
1123                 case AUD_CHANNELS_STEREO:
1124                         format = alGetEnumValue("AL_FORMAT_STEREO_FLOAT32");
1125                         break;
1126                 case AUD_CHANNELS_SURROUND4:
1127                         if(m_useMC)
1128                         {
1129                                 format = alGetEnumValue("AL_FORMAT_QUAD32");
1130                                 break;
1131                         }
1132                 case AUD_CHANNELS_SURROUND51:
1133                         if(m_useMC)
1134                         {
1135                                 format = alGetEnumValue("AL_FORMAT_51CHN32");
1136                                 break;
1137                         }
1138                 case AUD_CHANNELS_SURROUND61:
1139                         if(m_useMC)
1140                         {
1141                                 format = alGetEnumValue("AL_FORMAT_61CHN32");
1142                                 break;
1143                         }
1144                 case AUD_CHANNELS_SURROUND71:
1145                         if(m_useMC)
1146                         {
1147                                 format = alGetEnumValue("AL_FORMAT_71CHN32");
1148                                 break;
1149                         }
1150                 default:
1151                         valid = false;
1152                 }
1153                 break;
1154         default:
1155                 valid = false;
1156         }
1157
1158         if(!format)
1159                 valid = false;
1160
1161         return valid;
1162 }
1163
1164 AUD_Reference<AUD_IHandle> AUD_OpenALDevice::play(AUD_Reference<AUD_IReader> reader, bool keep)
1165 {
1166         AUD_Specs specs = reader->getSpecs();
1167
1168         // check format
1169         if(specs.channels == AUD_CHANNELS_INVALID)
1170                 return AUD_Reference<AUD_IHandle>();
1171
1172         if(m_specs.format != AUD_FORMAT_FLOAT32)
1173                 reader = new AUD_ConverterReader(reader, m_specs);
1174
1175         ALenum format;
1176
1177         if(!getFormat(format, specs))
1178                 return AUD_Reference<AUD_IHandle>();
1179
1180         lock();
1181         alcSuspendContext(m_context);
1182
1183         AUD_Reference<AUD_OpenALDevice::AUD_OpenALHandle> sound;
1184
1185         try
1186         {
1187                 // create the handle
1188                 sound = new AUD_OpenALDevice::AUD_OpenALHandle(this, format, reader, keep);
1189         }
1190         catch(AUD_Exception&)
1191         {
1192                 alcProcessContext(m_context);
1193                 unlock();
1194                 throw;
1195         }
1196
1197         alcProcessContext(m_context);
1198
1199         // play sound
1200         m_playingSounds.push_back(sound);
1201
1202         start();
1203
1204         unlock();
1205
1206         return AUD_Reference<AUD_IHandle>(sound);
1207 }
1208
1209 AUD_Reference<AUD_IHandle> AUD_OpenALDevice::play(AUD_Reference<AUD_IFactory> factory, bool keep)
1210 {
1211         /* AUD_XXX disabled
1212         AUD_OpenALHandle* sound = NULL;
1213
1214         lock();
1215
1216         try
1217         {
1218                 // check if it is a buffered factory
1219                 for(AUD_BFIterator i = m_bufferedFactories->begin();
1220                         i != m_bufferedFactories->end(); i++)
1221                 {
1222                         if((*i)->factory == factory)
1223                         {
1224                                 // create the handle
1225                                 sound = new AUD_OpenALHandle;
1226                                 sound->keep = keep;
1227                                 sound->current = -1;
1228                                 sound->isBuffered = true;
1229                                 sound->eos = true;
1230                                 sound->loopcount = 0;
1231                                 sound->stop = NULL;
1232                                 sound->stop_data = NULL;
1233
1234                                 alcSuspendContext(m_context);
1235
1236                                 // OpenAL playback code
1237                                 try
1238                                 {
1239                                         alGenSources(1, &sound->source);
1240                                         if(alGetError() != AL_NO_ERROR)
1241                                                 AUD_THROW(AUD_ERROR_OPENAL, gensource_error);
1242
1243                                         try
1244                                         {
1245                                                 alSourcei(sound->source, AL_BUFFER, (*i)->buffer);
1246                                                 if(alGetError() != AL_NO_ERROR)
1247                                                         AUD_THROW(AUD_ERROR_OPENAL, queue_error);
1248                                         }
1249                                         catch(AUD_Exception&)
1250                                         {
1251                                                 alDeleteSources(1, &sound->source);
1252                                                 throw;
1253                                         }
1254                                 }
1255                                 catch(AUD_Exception&)
1256                                 {
1257                                         delete sound;
1258                                         alcProcessContext(m_context);
1259                                         throw;
1260                                 }
1261
1262                                 // play sound
1263                                 m_playingSounds->push_back(sound);
1264
1265                                 alSourcei(sound->source, AL_SOURCE_RELATIVE, 1);
1266                                 start();
1267
1268                                 alcProcessContext(m_context);
1269                         }
1270                 }
1271         }
1272         catch(AUD_Exception&)
1273         {
1274                 unlock();
1275                 throw;
1276         }
1277
1278         unlock();
1279
1280         if(sound)
1281                 return sound;*/
1282
1283         return play(factory->createReader(), keep);
1284 }
1285
1286 void AUD_OpenALDevice::stopAll()
1287 {
1288         lock();
1289         alcSuspendContext(m_context);
1290
1291         while(!m_playingSounds.empty())
1292                 m_playingSounds.front()->stop();
1293
1294         while(!m_pausedSounds.empty())
1295                 m_pausedSounds.front()->stop();
1296
1297         alcProcessContext(m_context);
1298         unlock();
1299 }
1300
1301 void AUD_OpenALDevice::lock()
1302 {
1303         pthread_mutex_lock(&m_mutex);
1304 }
1305
1306 void AUD_OpenALDevice::unlock()
1307 {
1308         pthread_mutex_unlock(&m_mutex);
1309 }
1310
1311 float AUD_OpenALDevice::getVolume() const
1312 {
1313         float result;
1314         alGetListenerf(AL_GAIN, &result);
1315         return result;
1316 }
1317
1318 void AUD_OpenALDevice::setVolume(float volume)
1319 {
1320         alListenerf(AL_GAIN, volume);
1321 }
1322
1323 /* AUD_XXX Temorary disabled
1324
1325 bool AUD_OpenALDevice::bufferFactory(void *value)
1326 {
1327         bool result = false;
1328         AUD_IFactory* factory = (AUD_IFactory*) value;
1329
1330         // load the factory into an OpenAL buffer
1331         if(factory)
1332         {
1333                 // check if the factory is already buffered
1334                 lock();
1335                 for(AUD_BFIterator i = m_bufferedFactories->begin();
1336                         i != m_bufferedFactories->end(); i++)
1337                 {
1338                         if((*i)->factory == factory)
1339                         {
1340                                 result = true;
1341                                 break;
1342                         }
1343                 }
1344                 unlock();
1345                 if(result)
1346                         return result;
1347
1348                 AUD_IReader* reader = factory->createReader();
1349
1350                 if(reader == NULL)
1351                         return false;
1352
1353                 AUD_DeviceSpecs specs = m_specs;
1354                 specs.specs = reader->getSpecs();
1355
1356                 if(m_specs.format != AUD_FORMAT_FLOAT32)
1357                         reader = new AUD_ConverterReader(reader, m_specs);
1358
1359                 ALenum format;
1360
1361                 if(!getFormat(format, specs.specs))
1362                 {
1363                         return false;
1364                 }
1365
1366                 // load into a buffer
1367                 lock();
1368                 alcSuspendContext(m_context);
1369
1370                 AUD_OpenALBufferedFactory* bf = new AUD_OpenALBufferedFactory;
1371                 bf->factory = factory;
1372
1373                 try
1374                 {
1375                         alGenBuffers(1, &bf->buffer);
1376                         if(alGetError() != AL_NO_ERROR)
1377                                 AUD_THROW(AUD_ERROR_OPENAL);
1378
1379                         try
1380                         {
1381                                 sample_t* buf;
1382                                 int length = reader->getLength();
1383
1384                                 reader->read(length, buf);
1385                                 alBufferData(bf->buffer, format, buf,
1386                                                          length * AUD_DEVICE_SAMPLE_SIZE(specs),
1387                                                          specs.rate);
1388                                 if(alGetError() != AL_NO_ERROR)
1389                                         AUD_THROW(AUD_ERROR_OPENAL);
1390                         }
1391                         catch(AUD_Exception&)
1392                         {
1393                                 alDeleteBuffers(1, &bf->buffer);
1394                                 throw;
1395                         }
1396                 }
1397                 catch(AUD_Exception&)
1398                 {
1399                         delete bf;
1400                         alcProcessContext(m_context);
1401                         unlock();
1402                         return false;
1403                 }
1404
1405                 m_bufferedFactories->push_back(bf);
1406
1407                 alcProcessContext(m_context);
1408                 unlock();
1409         }
1410         else
1411         {
1412                 // stop all playing and paused buffered sources
1413                 lock();
1414                 alcSuspendContext(m_context);
1415
1416                 AUD_OpenALHandle* sound;
1417                 AUD_HandleIterator it = m_playingSounds->begin();
1418                 while(it != m_playingSounds->end())
1419                 {
1420                         sound = *it;
1421                         ++it;
1422
1423                         if(sound->isBuffered)
1424                                 stop(sound);
1425                 }
1426                 alcProcessContext(m_context);
1427
1428                 while(!m_bufferedFactories->empty())
1429                 {
1430                         alDeleteBuffers(1,
1431                                                         &(*(m_bufferedFactories->begin()))->buffer);
1432                         delete *m_bufferedFactories->begin();
1433                         m_bufferedFactories->erase(m_bufferedFactories->begin());
1434                 }
1435                 unlock();
1436         }
1437
1438         return true;
1439 }*/
1440
1441 /******************************************************************************/
1442 /**************************** 3D Device Code **********************************/
1443 /******************************************************************************/
1444
1445 AUD_Vector3 AUD_OpenALDevice::getListenerLocation() const
1446 {
1447         ALfloat p[3];
1448         alGetListenerfv(AL_POSITION, p);
1449         return AUD_Vector3(p[0], p[1], p[2]);
1450 }
1451
1452 void AUD_OpenALDevice::setListenerLocation(const AUD_Vector3& location)
1453 {
1454         alListenerfv(AL_POSITION, (ALfloat*)location.get());
1455 }
1456
1457 AUD_Vector3 AUD_OpenALDevice::getListenerVelocity() const
1458 {
1459         ALfloat v[3];
1460         alGetListenerfv(AL_VELOCITY, v);
1461         return AUD_Vector3(v[0], v[1], v[2]);
1462 }
1463
1464 void AUD_OpenALDevice::setListenerVelocity(const AUD_Vector3& velocity)
1465 {
1466         alListenerfv(AL_VELOCITY, (ALfloat*)velocity.get());
1467 }
1468
1469 AUD_Quaternion AUD_OpenALDevice::getListenerOrientation() const
1470 {
1471         return m_orientation;
1472 }
1473
1474 void AUD_OpenALDevice::setListenerOrientation(const AUD_Quaternion& orientation)
1475 {
1476         ALfloat direction[6];
1477         direction[0] = -2 * (orientation.w() * orientation.y() +
1478                                                  orientation.x() * orientation.z());
1479         direction[1] = 2 * (orientation.x() * orientation.w() -
1480                                                 orientation.z() * orientation.y());
1481         direction[2] = 2 * (orientation.x() * orientation.x() +
1482                                                 orientation.y() * orientation.y()) - 1;
1483         direction[3] = 2 * (orientation.x() * orientation.y() -
1484                                                 orientation.w() * orientation.z());
1485         direction[4] = 1 - 2 * (orientation.x() * orientation.x() +
1486                                                         orientation.z() * orientation.z());
1487         direction[5] = 2 * (orientation.w() * orientation.x() +
1488                                                 orientation.y() * orientation.z());
1489         alListenerfv(AL_ORIENTATION, direction);
1490         m_orientation = orientation;
1491 }
1492
1493 float AUD_OpenALDevice::getSpeedOfSound() const
1494 {
1495         return alGetFloat(AL_SPEED_OF_SOUND);
1496 }
1497
1498 void AUD_OpenALDevice::setSpeedOfSound(float speed)
1499 {
1500         alSpeedOfSound(speed);
1501 }
1502
1503 float AUD_OpenALDevice::getDopplerFactor() const
1504 {
1505         return alGetFloat(AL_DOPPLER_FACTOR);
1506 }
1507
1508 void AUD_OpenALDevice::setDopplerFactor(float factor)
1509 {
1510         alDopplerFactor(factor);
1511 }
1512
1513 AUD_DistanceModel AUD_OpenALDevice::getDistanceModel() const
1514 {
1515         switch(alGetInteger(AL_DISTANCE_MODEL))
1516         {
1517         case AL_INVERSE_DISTANCE:
1518                 return AUD_DISTANCE_MODEL_INVERSE;
1519         case AL_INVERSE_DISTANCE_CLAMPED:
1520                 return AUD_DISTANCE_MODEL_INVERSE_CLAMPED;
1521         case AL_LINEAR_DISTANCE:
1522                 return AUD_DISTANCE_MODEL_LINEAR;
1523         case AL_LINEAR_DISTANCE_CLAMPED:
1524                 return AUD_DISTANCE_MODEL_LINEAR_CLAMPED;
1525         case AL_EXPONENT_DISTANCE:
1526                 return AUD_DISTANCE_MODEL_EXPONENT;
1527         case AL_EXPONENT_DISTANCE_CLAMPED:
1528                 return AUD_DISTANCE_MODEL_EXPONENT_CLAMPED;
1529         default:
1530                 return AUD_DISTANCE_MODEL_INVALID;
1531         }
1532 }
1533
1534 void AUD_OpenALDevice::setDistanceModel(AUD_DistanceModel model)
1535 {
1536         switch(model)
1537         {
1538         case AUD_DISTANCE_MODEL_INVERSE:
1539                 alDistanceModel(AL_INVERSE_DISTANCE);
1540                 break;
1541         case AUD_DISTANCE_MODEL_INVERSE_CLAMPED:
1542                 alDistanceModel(AL_INVERSE_DISTANCE_CLAMPED);
1543                 break;
1544         case AUD_DISTANCE_MODEL_LINEAR:
1545                 alDistanceModel(AL_LINEAR_DISTANCE);
1546                 break;
1547         case AUD_DISTANCE_MODEL_LINEAR_CLAMPED:
1548                 alDistanceModel(AL_LINEAR_DISTANCE_CLAMPED);
1549                 break;
1550         case AUD_DISTANCE_MODEL_EXPONENT:
1551                 alDistanceModel(AL_EXPONENT_DISTANCE);
1552                 break;
1553         case AUD_DISTANCE_MODEL_EXPONENT_CLAMPED:
1554                 alDistanceModel(AL_EXPONENT_DISTANCE_CLAMPED);
1555                 break;
1556         default:
1557                 alDistanceModel(AL_NONE);
1558         }
1559 }