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