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