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