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