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