Blender  V2.59
AUD_OpenALDevice.cpp
Go to the documentation of this file.
00001 /*
00002  * $Id: AUD_OpenALDevice.cpp 38631 2011-07-23 16:08:37Z nexyon $
00003  *
00004  * ***** BEGIN GPL LICENSE BLOCK *****
00005  *
00006  * Copyright 2009-2011 Jörg Hermann Müller
00007  *
00008  * This file is part of AudaSpace.
00009  *
00010  * Audaspace is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version.
00014  *
00015  * AudaSpace is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License
00021  * along with Audaspace; if not, write to the Free Software Foundation,
00022  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00023  *
00024  * ***** END GPL LICENSE BLOCK *****
00025  */
00026 
00032 #include "AUD_OpenALDevice.h"
00033 #include "AUD_IFactory.h"
00034 #include "AUD_IReader.h"
00035 #include "AUD_ConverterReader.h"
00036 
00037 #include <cstring>
00038 #include <limits>
00039 
00040 #ifdef WIN32
00041 #include <windows.h>
00042 #else
00043 #include <unistd.h>
00044 #endif
00045 
00046 #define AUD_OPENAL_CYCLE_BUFFERS 3
00047 
00049 struct AUD_OpenALHandle : AUD_Handle
00050 {
00052         bool isBuffered;
00053 
00055         AUD_IReader* reader;
00056 
00058         bool keep;
00059 
00061         ALenum format;
00062 
00064         ALuint source;
00065 
00067         ALuint buffers[AUD_OPENAL_CYCLE_BUFFERS];
00068 
00070         int current;
00071 
00073         bool data_end;
00074 
00076         int loopcount;
00077 
00079         stopCallback stop;
00080 
00082         void* stop_data;
00083 };
00084 
00085 struct AUD_OpenALBufferedFactory
00086 {
00088         AUD_IFactory* factory;
00089 
00091         ALuint buffer;
00092 };
00093 
00094 typedef std::list<AUD_OpenALHandle*>::iterator AUD_HandleIterator;
00095 typedef std::list<AUD_OpenALBufferedFactory*>::iterator AUD_BFIterator;
00096 
00097 /******************************************************************************/
00098 /**************************** Threading Code **********************************/
00099 /******************************************************************************/
00100 
00101 void* AUD_openalRunThread(void* device)
00102 {
00103         AUD_OpenALDevice* dev = (AUD_OpenALDevice*)device;
00104         dev->updateStreams();
00105         return NULL;
00106 }
00107 
00108 void AUD_OpenALDevice::start(bool join)
00109 {
00110         lock();
00111 
00112         if(!m_playing)
00113         {
00114                 if(join)
00115                         pthread_join(m_thread, NULL);
00116 
00117                 pthread_attr_t attr;
00118                 pthread_attr_init(&attr);
00119                 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
00120 
00121                 pthread_create(&m_thread, &attr, AUD_openalRunThread, this);
00122 
00123                 pthread_attr_destroy(&attr);
00124 
00125                 m_playing = true;
00126         }
00127 
00128         unlock();
00129 }
00130 
00131 void AUD_OpenALDevice::updateStreams()
00132 {
00133         AUD_OpenALHandle* sound;
00134 
00135         int length;
00136         sample_t* buffer;
00137 
00138         ALint info;
00139         AUD_DeviceSpecs specs = m_specs;
00140         ALCenum cerr;
00141         std::list<AUD_OpenALHandle*> stopSounds;
00142         std::list<AUD_OpenALHandle*> pauseSounds;
00143         AUD_HandleIterator it;
00144 
00145         while(1)
00146         {
00147                 lock();
00148 
00149                 alcSuspendContext(m_context);
00150                 cerr = alcGetError(m_device);
00151                 if(cerr == ALC_NO_ERROR)
00152                 {
00153                         // for all sounds
00154                         for(it = m_playingSounds->begin(); it != m_playingSounds->end(); it++)
00155                         {
00156                                 sound = *it;
00157 
00158                                 // is it a streamed sound?
00159                                 if(!sound->isBuffered)
00160                                 {
00161                                         // check for buffer refilling
00162                                         alGetSourcei(sound->source, AL_BUFFERS_PROCESSED, &info);
00163 
00164                                         if(info)
00165                                         {
00166                                                 specs.specs = sound->reader->getSpecs();
00167 
00168                                                 // for all empty buffers
00169                                                 while(info--)
00170                                                 {
00171                                                         // if there's still data to play back
00172                                                         if(!sound->data_end)
00173                                                         {
00174                                                                 // read data
00175                                                                 length = m_buffersize;
00176                                                                 sound->reader->read(length, buffer);
00177 
00178                                                                 // looping necessary?
00179                                                                 if(length == 0 && sound->loopcount)
00180                                                                 {
00181                                                                         if(sound->loopcount > 0)
00182                                                                                 sound->loopcount--;
00183 
00184                                                                         sound->reader->seek(0);
00185 
00186                                                                         length = m_buffersize;
00187                                                                         sound->reader->read(length, buffer);
00188                                                                 }
00189 
00190                                                                 // read nothing?
00191                                                                 if(length == 0)
00192                                                                 {
00193                                                                         sound->data_end = true;
00194                                                                         break;
00195                                                                 }
00196 
00197                                                                 // unqueue buffer
00198                                                                 alSourceUnqueueBuffers(sound->source, 1,
00199                                                                                                 &sound->buffers[sound->current]);
00200                                                                 ALenum err;
00201                                                                 if((err = alGetError()) != AL_NO_ERROR)
00202                                                                 {
00203                                                                         sound->data_end = true;
00204                                                                         break;
00205                                                                 }
00206 
00207                                                                 // fill with new data
00208                                                                 alBufferData(sound->buffers[sound->current],
00209                                                                                          sound->format,
00210                                                                                          buffer, length *
00211                                                                                          AUD_DEVICE_SAMPLE_SIZE(specs),
00212                                                                                          specs.rate);
00213 
00214                                                                 if((err = alGetError()) != AL_NO_ERROR)
00215                                                                 {
00216                                                                         sound->data_end = true;
00217                                                                         break;
00218                                                                 }
00219 
00220                                                                 // and queue again
00221                                                                 alSourceQueueBuffers(sound->source, 1,
00222                                                                                                 &sound->buffers[sound->current]);
00223                                                                 if(alGetError() != AL_NO_ERROR)
00224                                                                 {
00225                                                                         sound->data_end = true;
00226                                                                         break;
00227                                                                 }
00228 
00229                                                                 sound->current = (sound->current+1) %
00230                                                                                                  AUD_OPENAL_CYCLE_BUFFERS;
00231                                                         }
00232                                                         else
00233                                                                 break;
00234                                                 }
00235                                         }
00236                                 }
00237 
00238                                 // check if the sound has been stopped
00239                                 alGetSourcei(sound->source, AL_SOURCE_STATE, &info);
00240 
00241                                 if(info != AL_PLAYING)
00242                                 {
00243                                         // if it really stopped
00244                                         if(sound->data_end)
00245                                         {
00246                                                 if(sound->stop)
00247                                                         sound->stop(sound->stop_data);
00248 
00249                                                 // pause or
00250                                                 if(sound->keep)
00251                                                         pauseSounds.push_back(sound);
00252                                                 // stop
00253                                                 else
00254                                                         stopSounds.push_back(sound);
00255                                         }
00256                                         // continue playing
00257                                         else
00258                                                 alSourcePlay(sound->source);
00259                                 }
00260                         }
00261 
00262                         for(it = pauseSounds.begin(); it != pauseSounds.end(); it++)
00263                                 pause(*it);
00264 
00265                         for(it = stopSounds.begin(); it != stopSounds.end(); it++)
00266                                 stop(*it);
00267 
00268                         pauseSounds.clear();
00269                         stopSounds.clear();
00270 
00271                         alcProcessContext(m_context);
00272                 }
00273 
00274                 // stop thread
00275                 if(m_playingSounds->empty() || (cerr != ALC_NO_ERROR))
00276                 {
00277                         m_playing = false;
00278                         unlock();
00279                         pthread_exit(NULL);
00280                 }
00281 
00282                 unlock();
00283 
00284 #ifdef WIN32
00285                 Sleep(20);
00286 #else
00287                 usleep(20000);
00288 #endif
00289         }
00290 }
00291 
00292 /******************************************************************************/
00293 /**************************** IDevice Code ************************************/
00294 /******************************************************************************/
00295 
00296 bool AUD_OpenALDevice::isValid(AUD_Handle* handle)
00297 {
00298         for(AUD_HandleIterator i = m_playingSounds->begin();
00299                 i != m_playingSounds->end(); i++)
00300                 if(*i == handle)
00301                         return true;
00302         for(AUD_HandleIterator i = m_pausedSounds->begin();
00303                 i != m_pausedSounds->end(); i++)
00304                 if(*i == handle)
00305                         return true;
00306         return false;
00307 }
00308 
00309 static const char* open_error = "AUD_OpenALDevice: Device couldn't be opened.";
00310 
00311 AUD_OpenALDevice::AUD_OpenALDevice(AUD_DeviceSpecs specs, int buffersize)
00312 {
00313         // cannot determine how many channels or which format OpenAL uses, but
00314         // it at least is able to play 16 bit stereo audio
00315         specs.channels = AUD_CHANNELS_STEREO;
00316         specs.format = AUD_FORMAT_S16;
00317 
00318 #if 0
00319         if(alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT") == AL_TRUE)
00320         {
00321                 ALCchar* devices = const_cast<ALCchar*>(alcGetString(NULL, ALC_DEVICE_SPECIFIER));
00322                 printf("OpenAL devices (standard is: %s):\n", alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER));
00323 
00324                 while(*devices)
00325                 {
00326                         printf("%s\n", devices);
00327                         devices += strlen(devices) + 1;
00328                 }
00329         }
00330 #endif
00331 
00332         m_device = alcOpenDevice(NULL);
00333 
00334         if(!m_device)
00335                 AUD_THROW(AUD_ERROR_OPENAL, open_error);
00336 
00337         // at least try to set the frequency
00338         ALCint attribs[] = { ALC_FREQUENCY, specs.rate, 0 };
00339         ALCint* attributes = attribs;
00340         if(specs.rate == AUD_RATE_INVALID)
00341                 attributes = NULL;
00342 
00343         m_context = alcCreateContext(m_device, attributes);
00344         alcMakeContextCurrent(m_context);
00345 
00346         alcGetIntegerv(m_device, ALC_FREQUENCY, 1, (ALCint*)&specs.rate);
00347 
00348         // check for specific formats and channel counts to be played back
00349         if(alIsExtensionPresent("AL_EXT_FLOAT32") == AL_TRUE)
00350                 specs.format = AUD_FORMAT_FLOAT32;
00351 
00352         m_useMC = alIsExtensionPresent("AL_EXT_MCFORMATS") == AL_TRUE;
00353 
00354         alGetError();
00355         alcGetError(m_device);
00356 
00357         m_specs = specs;
00358         m_buffersize = buffersize;
00359         m_playing = false;
00360 
00361         m_playingSounds = new std::list<AUD_OpenALHandle*>();
00362         m_pausedSounds = new std::list<AUD_OpenALHandle*>();
00363         m_bufferedFactories = new std::list<AUD_OpenALBufferedFactory*>();
00364 
00365         pthread_mutexattr_t attr;
00366         pthread_mutexattr_init(&attr);
00367         pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
00368 
00369         pthread_mutex_init(&m_mutex, &attr);
00370 
00371         pthread_mutexattr_destroy(&attr);
00372 
00373         start(false);
00374 }
00375 
00376 AUD_OpenALDevice::~AUD_OpenALDevice()
00377 {
00378         AUD_OpenALHandle* sound;
00379 
00380         lock();
00381         alcSuspendContext(m_context);
00382 
00383         // delete all playing sounds
00384         while(!m_playingSounds->empty())
00385         {
00386                 sound = *(m_playingSounds->begin());
00387                 alDeleteSources(1, &sound->source);
00388                 if(!sound->isBuffered)
00389                 {
00390                         delete sound->reader;
00391                         alDeleteBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers);
00392                 }
00393                 delete sound;
00394                 m_playingSounds->erase(m_playingSounds->begin());
00395         }
00396 
00397         // delete all paused sounds
00398         while(!m_pausedSounds->empty())
00399         {
00400                 sound = *(m_pausedSounds->begin());
00401                 alDeleteSources(1, &sound->source);
00402                 if(!sound->isBuffered)
00403                 {
00404                         delete sound->reader;
00405                         alDeleteBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers);
00406                 }
00407                 delete sound;
00408                 m_pausedSounds->erase(m_pausedSounds->begin());
00409         }
00410 
00411         // delete all buffered factories
00412         while(!m_bufferedFactories->empty())
00413         {
00414                 alDeleteBuffers(1, &(*(m_bufferedFactories->begin()))->buffer);
00415                 delete *m_bufferedFactories->begin();
00416                 m_bufferedFactories->erase(m_bufferedFactories->begin());
00417         }
00418 
00419         alcProcessContext(m_context);
00420 
00421         // wait for the thread to stop
00422         unlock();
00423         pthread_join(m_thread, NULL);
00424 
00425         delete m_playingSounds;
00426         delete m_pausedSounds;
00427         delete m_bufferedFactories;
00428 
00429         // quit OpenAL
00430         alcMakeContextCurrent(NULL);
00431         alcDestroyContext(m_context);
00432         alcCloseDevice(m_device);
00433 
00434         pthread_mutex_destroy(&m_mutex);
00435 }
00436 
00437 AUD_DeviceSpecs AUD_OpenALDevice::getSpecs() const
00438 {
00439         return m_specs;
00440 }
00441 
00442 bool AUD_OpenALDevice::getFormat(ALenum &format, AUD_Specs specs)
00443 {
00444         bool valid = true;
00445         format = 0;
00446 
00447         switch(m_specs.format)
00448         {
00449         case AUD_FORMAT_S16:
00450                 switch(specs.channels)
00451                 {
00452                 case AUD_CHANNELS_MONO:
00453                         format = AL_FORMAT_MONO16;
00454                         break;
00455                 case AUD_CHANNELS_STEREO:
00456                         format = AL_FORMAT_STEREO16;
00457                         break;
00458                 case AUD_CHANNELS_SURROUND4:
00459                         if(m_useMC)
00460                         {
00461                                 format = alGetEnumValue("AL_FORMAT_QUAD16");
00462                                 break;
00463                         }
00464                 case AUD_CHANNELS_SURROUND51:
00465                         if(m_useMC)
00466                         {
00467                                 format = alGetEnumValue("AL_FORMAT_51CHN16");
00468                                 break;
00469                         }
00470                 case AUD_CHANNELS_SURROUND61:
00471                         if(m_useMC)
00472                         {
00473                                 format = alGetEnumValue("AL_FORMAT_61CHN16");
00474                                 break;
00475                         }
00476                 case AUD_CHANNELS_SURROUND71:
00477                         if(m_useMC)
00478                         {
00479                                 format = alGetEnumValue("AL_FORMAT_71CHN16");
00480                                 break;
00481                         }
00482                 default:
00483                         valid = false;
00484                 }
00485                 break;
00486         case AUD_FORMAT_FLOAT32:
00487                 switch(specs.channels)
00488                 {
00489                 case AUD_CHANNELS_MONO:
00490                         format = alGetEnumValue("AL_FORMAT_MONO_FLOAT32");
00491                         break;
00492                 case AUD_CHANNELS_STEREO:
00493                         format = alGetEnumValue("AL_FORMAT_STEREO_FLOAT32");
00494                         break;
00495                 case AUD_CHANNELS_SURROUND4:
00496                         if(m_useMC)
00497                         {
00498                                 format = alGetEnumValue("AL_FORMAT_QUAD32");
00499                                 break;
00500                         }
00501                 case AUD_CHANNELS_SURROUND51:
00502                         if(m_useMC)
00503                         {
00504                                 format = alGetEnumValue("AL_FORMAT_51CHN32");
00505                                 break;
00506                         }
00507                 case AUD_CHANNELS_SURROUND61:
00508                         if(m_useMC)
00509                         {
00510                                 format = alGetEnumValue("AL_FORMAT_61CHN32");
00511                                 break;
00512                         }
00513                 case AUD_CHANNELS_SURROUND71:
00514                         if(m_useMC)
00515                         {
00516                                 format = alGetEnumValue("AL_FORMAT_71CHN32");
00517                                 break;
00518                         }
00519                 default:
00520                         valid = false;
00521                 }
00522                 break;
00523         default:
00524                 valid = false;
00525         }
00526 
00527         if(!format)
00528                 valid = false;
00529 
00530         return valid;
00531 }
00532 
00533 static const char* genbuffer_error = "AUD_OpenALDevice: Buffer couldn't be "
00534                                                                          "generated.";
00535 static const char* gensource_error = "AUD_OpenALDevice: Source couldn't be "
00536                                                                          "generated.";
00537 static const char* queue_error = "AUD_OpenALDevice: Buffer couldn't be "
00538                                                                  "queued to the source.";
00539 static const char* bufferdata_error = "AUD_OpenALDevice: Buffer couldn't be "
00540                                                                           "filled with data.";
00541 
00542 AUD_Handle* AUD_OpenALDevice::play(AUD_IReader* reader, bool keep)
00543 {
00544         AUD_OpenALHandle* sound = NULL;
00545 
00546         AUD_DeviceSpecs specs = m_specs;
00547         specs.specs = reader->getSpecs();
00548 
00549         // check format
00550         bool valid = specs.channels != AUD_CHANNELS_INVALID;
00551 
00552         if(m_specs.format != AUD_FORMAT_FLOAT32)
00553                 reader = new AUD_ConverterReader(reader, m_specs);
00554 
00555         // create the handle
00556         sound = new AUD_OpenALHandle;
00557         sound->keep = keep;
00558         sound->reader = reader;
00559         sound->current = 0;
00560         sound->isBuffered = false;
00561         sound->data_end = false;
00562         sound->loopcount = 0;
00563         sound->stop = NULL;
00564         sound->stop_data = NULL;
00565 
00566         valid &= getFormat(sound->format, specs.specs);
00567 
00568         if(!valid)
00569         {
00570                 delete sound;
00571                 delete reader;
00572                 return NULL;
00573         }
00574 
00575         lock();
00576         alcSuspendContext(m_context);
00577 
00578         // OpenAL playback code
00579         try
00580         {
00581                 alGenBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers);
00582                 if(alGetError() != AL_NO_ERROR)
00583                         AUD_THROW(AUD_ERROR_OPENAL, genbuffer_error);
00584 
00585                 try
00586                 {
00587                         sample_t* buf;
00588                         int length;
00589 
00590                         for(int i = 0; i < AUD_OPENAL_CYCLE_BUFFERS; i++)
00591                         {
00592                                 length = m_buffersize;
00593                                 reader->read(length, buf);
00594                                 alBufferData(sound->buffers[i], sound->format, buf,
00595                                                          length * AUD_DEVICE_SAMPLE_SIZE(specs),
00596                                                          specs.rate);
00597                                 if(alGetError() != AL_NO_ERROR)
00598                                         AUD_THROW(AUD_ERROR_OPENAL, bufferdata_error);
00599                         }
00600 
00601                         alGenSources(1, &sound->source);
00602                         if(alGetError() != AL_NO_ERROR)
00603                                 AUD_THROW(AUD_ERROR_OPENAL, gensource_error);
00604 
00605                         try
00606                         {
00607                                 alSourceQueueBuffers(sound->source, AUD_OPENAL_CYCLE_BUFFERS,
00608                                                                          sound->buffers);
00609                                 if(alGetError() != AL_NO_ERROR)
00610                                         AUD_THROW(AUD_ERROR_OPENAL, queue_error);
00611                         }
00612                         catch(AUD_Exception&)
00613                         {
00614                                 alDeleteSources(1, &sound->source);
00615                                 throw;
00616                         }
00617                 }
00618                 catch(AUD_Exception&)
00619                 {
00620                         alDeleteBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers);
00621                         throw;
00622                 }
00623         }
00624         catch(AUD_Exception&)
00625         {
00626                 delete sound;
00627                 delete reader;
00628                 alcProcessContext(m_context);
00629                 unlock();
00630                 throw;
00631         }
00632 
00633         // play sound
00634         m_playingSounds->push_back(sound);
00635         alSourcei(sound->source, AL_SOURCE_RELATIVE, 1);
00636 
00637         start();
00638 
00639         alcProcessContext(m_context);
00640         unlock();
00641 
00642         return sound;
00643 }
00644 
00645 AUD_Handle* AUD_OpenALDevice::play(AUD_IFactory* factory, bool keep)
00646 {
00647         AUD_OpenALHandle* sound = NULL;
00648 
00649         lock();
00650 
00651         try
00652         {
00653                 // check if it is a buffered factory
00654                 for(AUD_BFIterator i = m_bufferedFactories->begin();
00655                         i != m_bufferedFactories->end(); i++)
00656                 {
00657                         if((*i)->factory == factory)
00658                         {
00659                                 // create the handle
00660                                 sound = new AUD_OpenALHandle;
00661                                 sound->keep = keep;
00662                                 sound->current = -1;
00663                                 sound->isBuffered = true;
00664                                 sound->data_end = true;
00665                                 sound->loopcount = 0;
00666                                 sound->stop = NULL;
00667                                 sound->stop_data = NULL;
00668 
00669                                 alcSuspendContext(m_context);
00670 
00671                                 // OpenAL playback code
00672                                 try
00673                                 {
00674                                         alGenSources(1, &sound->source);
00675                                         if(alGetError() != AL_NO_ERROR)
00676                                                 AUD_THROW(AUD_ERROR_OPENAL, gensource_error);
00677 
00678                                         try
00679                                         {
00680                                                 alSourcei(sound->source, AL_BUFFER, (*i)->buffer);
00681                                                 if(alGetError() != AL_NO_ERROR)
00682                                                         AUD_THROW(AUD_ERROR_OPENAL, queue_error);
00683                                         }
00684                                         catch(AUD_Exception&)
00685                                         {
00686                                                 alDeleteSources(1, &sound->source);
00687                                                 throw;
00688                                         }
00689                                 }
00690                                 catch(AUD_Exception&)
00691                                 {
00692                                         delete sound;
00693                                         alcProcessContext(m_context);
00694                                         throw;
00695                                 }
00696 
00697                                 // play sound
00698                                 m_playingSounds->push_back(sound);
00699 
00700                                 alSourcei(sound->source, AL_SOURCE_RELATIVE, 1);
00701                                 start();
00702 
00703                                 alcProcessContext(m_context);
00704                         }
00705                 }
00706         }
00707         catch(AUD_Exception&)
00708         {
00709                 unlock();
00710                 throw;
00711         }
00712 
00713         unlock();
00714 
00715         if(sound)
00716                 return sound;
00717 
00718         return play(factory->createReader(), keep);
00719 }
00720 
00721 bool AUD_OpenALDevice::pause(AUD_Handle* handle)
00722 {
00723         bool result = false;
00724 
00725         lock();
00726 
00727         // only songs that are played can be paused
00728         for(AUD_HandleIterator i = m_playingSounds->begin();
00729                 i != m_playingSounds->end(); i++)
00730         {
00731                 if(*i == handle)
00732                 {
00733                         m_pausedSounds->push_back(*i);
00734                         alSourcePause((*i)->source);
00735                         m_playingSounds->erase(i);
00736                         result = true;
00737                         break;
00738                 }
00739         }
00740 
00741         unlock();
00742 
00743         return result;
00744 }
00745 
00746 bool AUD_OpenALDevice::resume(AUD_Handle* handle)
00747 {
00748         bool result = false;
00749 
00750         lock();
00751 
00752         // only songs that are paused can be resumed
00753         for(AUD_HandleIterator i = m_pausedSounds->begin();
00754                 i != m_pausedSounds->end(); i++)
00755         {
00756                 if(*i == handle)
00757                 {
00758                         m_playingSounds->push_back(*i);
00759                         start();
00760                         m_pausedSounds->erase(i);
00761                         result = true;
00762                         break;
00763                 }
00764         }
00765 
00766         unlock();
00767 
00768         return result;
00769 }
00770 
00771 bool AUD_OpenALDevice::stop(AUD_Handle* handle)
00772 {
00773         AUD_OpenALHandle* sound;
00774 
00775         bool result = false;
00776 
00777         lock();
00778 
00779         for(AUD_HandleIterator i = m_playingSounds->begin();
00780                 i != m_playingSounds->end(); i++)
00781         {
00782                 if(*i == handle)
00783                 {
00784                         sound = *i;
00785                         alDeleteSources(1, &sound->source);
00786                         if(!sound->isBuffered)
00787                         {
00788                                 delete sound->reader;
00789                                 alDeleteBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers);
00790                         }
00791                         delete *i;
00792                         m_playingSounds->erase(i);
00793                         result = true;
00794                         break;
00795                 }
00796         }
00797         if(!result)
00798         {
00799                 for(AUD_HandleIterator i = m_pausedSounds->begin();
00800                         i != m_pausedSounds->end(); i++)
00801                 {
00802                         if(*i == handle)
00803                         {
00804                                 sound = *i;
00805                                 alDeleteSources(1, &sound->source);
00806                                 if(!sound->isBuffered)
00807                                 {
00808                                         delete sound->reader;
00809                                         alDeleteBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers);
00810                                 }
00811                                 delete *i;
00812                                 m_pausedSounds->erase(i);
00813                                 result = true;
00814                                 break;
00815                         }
00816                 }
00817         }
00818 
00819         unlock();
00820 
00821         return result;
00822 }
00823 
00824 bool AUD_OpenALDevice::getKeep(AUD_Handle* handle)
00825 {
00826         bool result = false;
00827 
00828         lock();
00829 
00830         if(isValid(handle))
00831                 result = ((AUD_OpenALHandle*)handle)->keep;
00832 
00833         unlock();
00834 
00835         return result;
00836 }
00837 
00838 bool AUD_OpenALDevice::setKeep(AUD_Handle* handle, bool keep)
00839 {
00840         bool result = false;
00841 
00842         lock();
00843 
00844         if(isValid(handle))
00845         {
00846                 ((AUD_OpenALHandle*)handle)->keep = keep;
00847                 result = true;
00848         }
00849 
00850         unlock();
00851 
00852         return result;
00853 }
00854 
00855 bool AUD_OpenALDevice::seek(AUD_Handle* handle, float position)
00856 {
00857         bool result = false;
00858 
00859         lock();
00860 
00861         if(isValid(handle))
00862         {
00863                 AUD_OpenALHandle* alhandle = (AUD_OpenALHandle*)handle;
00864                 if(alhandle->isBuffered)
00865                         alSourcef(alhandle->source, AL_SEC_OFFSET, position);
00866                 else
00867                 {
00868                         alhandle->reader->seek((int)(position *
00869                                                                                  alhandle->reader->getSpecs().rate));
00870                         alhandle->data_end = false;
00871 
00872                         ALint info;
00873 
00874                         alGetSourcei(alhandle->source, AL_SOURCE_STATE, &info);
00875 
00876                         if(info != AL_PLAYING)
00877                         {
00878                                 if(info == AL_PAUSED)
00879                                         alSourceStop(alhandle->source);
00880 
00881                                 alSourcei(alhandle->source, AL_BUFFER, 0);
00882                                 alhandle->current = 0;
00883 
00884                                 ALenum err;
00885                                 if((err = alGetError()) == AL_NO_ERROR)
00886                                 {
00887                                         sample_t* buf;
00888                                         int length;
00889                                         AUD_DeviceSpecs specs = m_specs;
00890                                         specs.specs = alhandle->reader->getSpecs();
00891 
00892                                         for(int i = 0; i < AUD_OPENAL_CYCLE_BUFFERS; i++)
00893                                         {
00894                                                 length = m_buffersize;
00895                                                 alhandle->reader->read(length, buf);
00896                                                 alBufferData(alhandle->buffers[i], alhandle->format,
00897                                                                          buf,
00898                                                                          length * AUD_DEVICE_SAMPLE_SIZE(specs),
00899                                                                          specs.rate);
00900 
00901                                                 if(alGetError() != AL_NO_ERROR)
00902                                                         break;
00903                                         }
00904 
00905                                         alSourceQueueBuffers(alhandle->source,
00906                                                                                  AUD_OPENAL_CYCLE_BUFFERS,
00907                                                                                  alhandle->buffers);
00908                                 }
00909 
00910                                 alSourceRewind(alhandle->source);
00911                         }
00912                 }
00913                 result = true;
00914         }
00915 
00916         unlock();
00917         return result;
00918 }
00919 
00920 float AUD_OpenALDevice::getPosition(AUD_Handle* handle)
00921 {
00922         float position = 0.0f;
00923 
00924         lock();
00925 
00926         if(isValid(handle))
00927         {
00928                 AUD_OpenALHandle* h = (AUD_OpenALHandle*)handle;
00929                 alGetSourcef(h->source, AL_SEC_OFFSET, &position);
00930                 if(!h->isBuffered)
00931                 {
00932                         AUD_Specs specs = h->reader->getSpecs();
00933                         position += (h->reader->getPosition() - m_buffersize *
00934                                                                         AUD_OPENAL_CYCLE_BUFFERS) /
00935                                            (float)specs.rate;
00936                 }
00937         }
00938 
00939         unlock();
00940         return position;
00941 }
00942 
00943 AUD_Status AUD_OpenALDevice::getStatus(AUD_Handle* handle)
00944 {
00945         AUD_Status status = AUD_STATUS_INVALID;
00946 
00947         lock();
00948 
00949         for(AUD_HandleIterator i = m_playingSounds->begin();
00950                 i != m_playingSounds->end(); i++)
00951         {
00952                 if(*i == handle)
00953                 {
00954                         status = AUD_STATUS_PLAYING;
00955                         break;
00956                 }
00957         }
00958         if(status == AUD_STATUS_INVALID)
00959         {
00960                 for(AUD_HandleIterator i = m_pausedSounds->begin();
00961                         i != m_pausedSounds->end(); i++)
00962                 {
00963                         if(*i == handle)
00964                         {
00965                                 status = AUD_STATUS_PAUSED;
00966                                 break;
00967                         }
00968                 }
00969         }
00970 
00971         unlock();
00972 
00973         return status;
00974 }
00975 
00976 void AUD_OpenALDevice::lock()
00977 {
00978         pthread_mutex_lock(&m_mutex);
00979 }
00980 
00981 void AUD_OpenALDevice::unlock()
00982 {
00983         pthread_mutex_unlock(&m_mutex);
00984 }
00985 
00986 float AUD_OpenALDevice::getVolume() const
00987 {
00988         float result;
00989         alGetListenerf(AL_GAIN, &result);
00990         return result;
00991 }
00992 
00993 void AUD_OpenALDevice::setVolume(float volume)
00994 {
00995         alListenerf(AL_GAIN, volume);
00996 }
00997 
00998 float AUD_OpenALDevice::getVolume(AUD_Handle* handle)
00999 {
01000         lock();
01001         float result = std::numeric_limits<float>::quiet_NaN();
01002         if(isValid(handle))
01003                 alGetSourcef(((AUD_OpenALHandle*)handle)->source,AL_GAIN, &result);
01004         unlock();
01005         return result;
01006 }
01007 
01008 bool AUD_OpenALDevice::setVolume(AUD_Handle* handle, float volume)
01009 {
01010         lock();
01011         bool result = isValid(handle);
01012         if(result)
01013                 alSourcef(((AUD_OpenALHandle*)handle)->source, AL_GAIN, volume);
01014         unlock();
01015         return result;
01016 }
01017 
01018 float AUD_OpenALDevice::getPitch(AUD_Handle* handle)
01019 {
01020         lock();
01021         float result = std::numeric_limits<float>::quiet_NaN();
01022         if(isValid(handle))
01023                 alGetSourcef(((AUD_OpenALHandle*)handle)->source,AL_PITCH, &result);
01024         unlock();
01025         return result;
01026 }
01027 
01028 bool AUD_OpenALDevice::setPitch(AUD_Handle* handle, float pitch)
01029 {
01030         lock();
01031         bool result = isValid(handle);
01032         if(result)
01033                 alSourcef(((AUD_OpenALHandle*)handle)->source, AL_PITCH, pitch);
01034         unlock();
01035         return result;
01036 }
01037 
01038 int AUD_OpenALDevice::getLoopCount(AUD_Handle* handle)
01039 {
01040         lock();
01041         int result = 0;
01042         if(isValid(handle))
01043                 result = ((AUD_OpenALHandle*)handle)->loopcount;
01044         unlock();
01045         return result;
01046 }
01047 
01048 bool AUD_OpenALDevice::setLoopCount(AUD_Handle* handle, int count)
01049 {
01050         lock();
01051         bool result = isValid(handle);
01052         if(result)
01053                 ((AUD_OpenALHandle*)handle)->loopcount = count;
01054         unlock();
01055         return result;
01056 }
01057 
01058 bool AUD_OpenALDevice::setStopCallback(AUD_Handle* handle, stopCallback callback, void* data)
01059 {
01060         lock();
01061         bool result = isValid(handle);
01062         if(result)
01063         {
01064                 AUD_OpenALHandle* h = (AUD_OpenALHandle*)handle;
01065                 h->stop = callback;
01066                 h->stop_data = data;
01067         }
01068         unlock();
01069         return result;
01070 }
01071 
01072 /* AUD_XXX Temorary disabled
01073 
01074 bool AUD_OpenALDevice::bufferFactory(void *value)
01075 {
01076         bool result = false;
01077         AUD_IFactory* factory = (AUD_IFactory*) value;
01078 
01079         // load the factory into an OpenAL buffer
01080         if(factory)
01081         {
01082                 // check if the factory is already buffered
01083                 lock();
01084                 for(AUD_BFIterator i = m_bufferedFactories->begin();
01085                         i != m_bufferedFactories->end(); i++)
01086                 {
01087                         if((*i)->factory == factory)
01088                         {
01089                                 result = true;
01090                                 break;
01091                         }
01092                 }
01093                 unlock();
01094                 if(result)
01095                         return result;
01096 
01097                 AUD_IReader* reader = factory->createReader();
01098 
01099                 if(reader == NULL)
01100                         return false;
01101 
01102                 AUD_DeviceSpecs specs = m_specs;
01103                 specs.specs = reader->getSpecs();
01104 
01105                 if(m_specs.format != AUD_FORMAT_FLOAT32)
01106                         reader = new AUD_ConverterReader(reader, m_specs);
01107 
01108                 ALenum format;
01109 
01110                 if(!getFormat(format, specs.specs))
01111                 {
01112                         delete reader;
01113                         return false;
01114                 }
01115 
01116                 // load into a buffer
01117                 lock();
01118                 alcSuspendContext(m_context);
01119 
01120                 AUD_OpenALBufferedFactory* bf = new AUD_OpenALBufferedFactory;
01121                 bf->factory = factory;
01122 
01123                 try
01124                 {
01125                         alGenBuffers(1, &bf->buffer);
01126                         if(alGetError() != AL_NO_ERROR)
01127                                 AUD_THROW(AUD_ERROR_OPENAL);
01128 
01129                         try
01130                         {
01131                                 sample_t* buf;
01132                                 int length = reader->getLength();
01133 
01134                                 reader->read(length, buf);
01135                                 alBufferData(bf->buffer, format, buf,
01136                                                          length * AUD_DEVICE_SAMPLE_SIZE(specs),
01137                                                          specs.rate);
01138                                 if(alGetError() != AL_NO_ERROR)
01139                                         AUD_THROW(AUD_ERROR_OPENAL);
01140                         }
01141                         catch(AUD_Exception&)
01142                         {
01143                                 alDeleteBuffers(1, &bf->buffer);
01144                                 throw;
01145                         }
01146                 }
01147                 catch(AUD_Exception&)
01148                 {
01149                         delete bf;
01150                         delete reader;
01151                         alcProcessContext(m_context);
01152                         unlock();
01153                         return false;
01154                 }
01155 
01156                 m_bufferedFactories->push_back(bf);
01157 
01158                 alcProcessContext(m_context);
01159                 unlock();
01160         }
01161         else
01162         {
01163                 // stop all playing and paused buffered sources
01164                 lock();
01165                 alcSuspendContext(m_context);
01166 
01167                 AUD_OpenALHandle* sound;
01168                 AUD_HandleIterator it = m_playingSounds->begin();
01169                 while(it != m_playingSounds->end())
01170                 {
01171                         sound = *it;
01172                         ++it;
01173 
01174                         if(sound->isBuffered)
01175                                 stop(sound);
01176                 }
01177                 alcProcessContext(m_context);
01178 
01179                 while(!m_bufferedFactories->empty())
01180                 {
01181                         alDeleteBuffers(1,
01182                                                         &(*(m_bufferedFactories->begin()))->buffer);
01183                         delete *m_bufferedFactories->begin();
01184                         m_bufferedFactories->erase(m_bufferedFactories->begin());
01185                 }
01186                 unlock();
01187         }
01188 
01189         return true;
01190 }*/
01191 
01192 /******************************************************************************/
01193 /**************************** 3D Device Code **********************************/
01194 /******************************************************************************/
01195 
01196 AUD_Vector3 AUD_OpenALDevice::getListenerLocation() const
01197 {
01198         ALfloat p[3];
01199         alGetListenerfv(AL_POSITION, p);
01200         return AUD_Vector3(p[0], p[1], p[2]);
01201 }
01202 
01203 void AUD_OpenALDevice::setListenerLocation(const AUD_Vector3& location)
01204 {
01205         alListenerfv(AL_POSITION, (ALfloat*)location.get());
01206 }
01207 
01208 AUD_Vector3 AUD_OpenALDevice::getListenerVelocity() const
01209 {
01210         ALfloat v[3];
01211         alGetListenerfv(AL_VELOCITY, v);
01212         return AUD_Vector3(v[0], v[1], v[2]);
01213 }
01214 
01215 void AUD_OpenALDevice::setListenerVelocity(const AUD_Vector3& velocity)
01216 {
01217         alListenerfv(AL_VELOCITY, (ALfloat*)velocity.get());
01218 }
01219 
01220 AUD_Quaternion AUD_OpenALDevice::getListenerOrientation() const
01221 {
01222         // AUD_XXX not implemented yet
01223         return AUD_Quaternion(0, 0, 0, 0);
01224 }
01225 
01226 void AUD_OpenALDevice::setListenerOrientation(const AUD_Quaternion& orientation)
01227 {
01228         ALfloat direction[6];
01229         direction[0] = -2 * (orientation.w() * orientation.y() +
01230                                                  orientation.x() * orientation.z());
01231         direction[1] = 2 * (orientation.x() * orientation.w() -
01232                                                 orientation.z() * orientation.y());
01233         direction[2] = 2 * (orientation.x() * orientation.x() +
01234                                                 orientation.y() * orientation.y()) - 1;
01235         direction[3] = 2 * (orientation.x() * orientation.y() -
01236                                                 orientation.w() * orientation.z());
01237         direction[4] = 1 - 2 * (orientation.x() * orientation.x() +
01238                                                         orientation.z() * orientation.z());
01239         direction[5] = 2 * (orientation.w() * orientation.x() +
01240                                                 orientation.y() * orientation.z());
01241         alListenerfv(AL_ORIENTATION, direction);
01242 }
01243 
01244 float AUD_OpenALDevice::getSpeedOfSound() const
01245 {
01246         return alGetFloat(AL_SPEED_OF_SOUND);
01247 }
01248 
01249 void AUD_OpenALDevice::setSpeedOfSound(float speed)
01250 {
01251         alSpeedOfSound(speed);
01252 }
01253 
01254 float AUD_OpenALDevice::getDopplerFactor() const
01255 {
01256         return alGetFloat(AL_DOPPLER_FACTOR);
01257 }
01258 
01259 void AUD_OpenALDevice::setDopplerFactor(float factor)
01260 {
01261         alDopplerFactor(factor);
01262 }
01263 
01264 AUD_DistanceModel AUD_OpenALDevice::getDistanceModel() const
01265 {
01266         switch(alGetInteger(AL_DISTANCE_MODEL))
01267         {
01268         case AL_INVERSE_DISTANCE:
01269                 return AUD_DISTANCE_MODEL_INVERSE;
01270         case AL_INVERSE_DISTANCE_CLAMPED:
01271                 return AUD_DISTANCE_MODEL_INVERSE_CLAMPED;
01272         case AL_LINEAR_DISTANCE:
01273                 return AUD_DISTANCE_MODEL_LINEAR;
01274         case AL_LINEAR_DISTANCE_CLAMPED:
01275                 return AUD_DISTANCE_MODEL_LINEAR_CLAMPED;
01276         case AL_EXPONENT_DISTANCE:
01277                 return AUD_DISTANCE_MODEL_EXPONENT;
01278         case AL_EXPONENT_DISTANCE_CLAMPED:
01279                 return AUD_DISTANCE_MODEL_EXPONENT_CLAMPED;
01280         default:
01281                 return AUD_DISTANCE_MODEL_INVALID;
01282         }
01283 }
01284 
01285 void AUD_OpenALDevice::setDistanceModel(AUD_DistanceModel model)
01286 {
01287         switch(model)
01288         {
01289         case AUD_DISTANCE_MODEL_INVERSE:
01290                 alDistanceModel(AL_INVERSE_DISTANCE);
01291                 break;
01292         case AUD_DISTANCE_MODEL_INVERSE_CLAMPED:
01293                 alDistanceModel(AL_INVERSE_DISTANCE_CLAMPED);
01294                 break;
01295         case AUD_DISTANCE_MODEL_LINEAR:
01296                 alDistanceModel(AL_LINEAR_DISTANCE);
01297                 break;
01298         case AUD_DISTANCE_MODEL_LINEAR_CLAMPED:
01299                 alDistanceModel(AL_LINEAR_DISTANCE_CLAMPED);
01300                 break;
01301         case AUD_DISTANCE_MODEL_EXPONENT:
01302                 alDistanceModel(AL_EXPONENT_DISTANCE);
01303                 break;
01304         case AUD_DISTANCE_MODEL_EXPONENT_CLAMPED:
01305                 alDistanceModel(AL_EXPONENT_DISTANCE_CLAMPED);
01306                 break;
01307         default:
01308                 alDistanceModel(AL_NONE);
01309         }
01310 }
01311 
01312 AUD_Vector3 AUD_OpenALDevice::getSourceLocation(AUD_Handle* handle)
01313 {
01314         AUD_Vector3 result = AUD_Vector3(0, 0, 0);
01315         ALfloat p[3];
01316         lock();
01317 
01318         if(isValid(handle))
01319         {
01320                 alGetSourcefv(((AUD_OpenALHandle*)handle)->source, AL_POSITION, p);
01321                 result = AUD_Vector3(p[0], p[1], p[2]);
01322         }
01323 
01324         unlock();
01325         return result;
01326 }
01327 
01328 bool AUD_OpenALDevice::setSourceLocation(AUD_Handle* handle, const AUD_Vector3& location)
01329 {
01330         lock();
01331         bool result = isValid(handle);
01332 
01333         if(result)
01334                 alSourcefv(((AUD_OpenALHandle*)handle)->source, AL_POSITION,
01335                                    (ALfloat*)location.get());
01336 
01337         unlock();
01338         return result;
01339 }
01340 
01341 AUD_Vector3 AUD_OpenALDevice::getSourceVelocity(AUD_Handle* handle)
01342 {
01343         AUD_Vector3 result = AUD_Vector3(0, 0, 0);
01344         ALfloat v[3];
01345         lock();
01346 
01347         if(isValid(handle))
01348         {
01349                 alGetSourcefv(((AUD_OpenALHandle*)handle)->source, AL_VELOCITY, v);
01350                 result = AUD_Vector3(v[0], v[1], v[2]);
01351         }
01352 
01353         unlock();
01354         return result;
01355 }
01356 
01357 bool AUD_OpenALDevice::setSourceVelocity(AUD_Handle* handle, const AUD_Vector3& velocity)
01358 {
01359         lock();
01360         bool result = isValid(handle);
01361 
01362         if(result)
01363                 alSourcefv(((AUD_OpenALHandle*)handle)->source, AL_VELOCITY,
01364                                    (ALfloat*)velocity.get());
01365 
01366         unlock();
01367         return result;
01368 }
01369 
01370 AUD_Quaternion AUD_OpenALDevice::getSourceOrientation(AUD_Handle* handle)
01371 {
01372         // AUD_XXX not implemented yet
01373         return AUD_Quaternion(0, 0, 0, 0);
01374 }
01375 
01376 bool AUD_OpenALDevice::setSourceOrientation(AUD_Handle* handle, const AUD_Quaternion& orientation)
01377 {
01378         lock();
01379         bool result = isValid(handle);
01380 
01381         if(result)
01382         {
01383                 ALfloat direction[3];
01384                 direction[0] = -2 * (orientation.w() * orientation.y() +
01385                                                          orientation.x() * orientation.z());
01386                 direction[1] = 2 * (orientation.x() * orientation.w() -
01387                                                         orientation.z() * orientation.y());
01388                 direction[2] = 2 * (orientation.x() * orientation.x() +
01389                                                         orientation.y() * orientation.y()) - 1;
01390                 alSourcefv(((AUD_OpenALHandle*)handle)->source, AL_DIRECTION,
01391                                    direction);
01392         }
01393 
01394         unlock();
01395         return result;
01396 }
01397 
01398 bool AUD_OpenALDevice::isRelative(AUD_Handle* handle)
01399 {
01400         int result = std::numeric_limits<float>::quiet_NaN();;
01401 
01402         lock();
01403 
01404         if(isValid(handle))
01405                 alGetSourcei(((AUD_OpenALHandle*)handle)->source, AL_SOURCE_RELATIVE,
01406                                          &result);
01407 
01408         unlock();
01409         return result;
01410 }
01411 
01412 bool AUD_OpenALDevice::setRelative(AUD_Handle* handle, bool relative)
01413 {
01414         lock();
01415         bool result = isValid(handle);
01416 
01417         if(result)
01418                 alSourcei(((AUD_OpenALHandle*)handle)->source, AL_SOURCE_RELATIVE,
01419                                   relative);
01420 
01421         unlock();
01422         return result;
01423 }
01424 
01425 float AUD_OpenALDevice::getVolumeMaximum(AUD_Handle* handle)
01426 {
01427         float result = std::numeric_limits<float>::quiet_NaN();;
01428 
01429         lock();
01430 
01431         if(isValid(handle))
01432                 alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_MAX_GAIN,
01433                                          &result);
01434 
01435         unlock();
01436         return result;
01437 }
01438 
01439 bool AUD_OpenALDevice::setVolumeMaximum(AUD_Handle* handle, float volume)
01440 {
01441         lock();
01442         bool result = isValid(handle);
01443 
01444         if(result)
01445 
01446                 alSourcef(((AUD_OpenALHandle*)handle)->source, AL_MAX_GAIN,
01447                                   volume);
01448 
01449         unlock();
01450         return result;
01451 }
01452 
01453 float AUD_OpenALDevice::getVolumeMinimum(AUD_Handle* handle)
01454 {
01455         float result = std::numeric_limits<float>::quiet_NaN();;
01456 
01457         lock();
01458 
01459         if(isValid(handle))
01460                 alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_MIN_GAIN,
01461                                          &result);
01462 
01463         unlock();
01464         return result;
01465 }
01466 
01467 bool AUD_OpenALDevice::setVolumeMinimum(AUD_Handle* handle, float volume)
01468 {
01469         lock();
01470         bool result = isValid(handle);
01471 
01472         if(result)
01473                 alSourcef(((AUD_OpenALHandle*)handle)->source, AL_MIN_GAIN,
01474                                   volume);
01475 
01476         unlock();
01477         return result;
01478 }
01479 
01480 float AUD_OpenALDevice::getDistanceMaximum(AUD_Handle* handle)
01481 {
01482         float result = std::numeric_limits<float>::quiet_NaN();;
01483 
01484         lock();
01485 
01486         if(isValid(handle))
01487                 alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_MAX_DISTANCE,
01488                                          &result);
01489 
01490         unlock();
01491         return result;
01492 }
01493 
01494 bool AUD_OpenALDevice::setDistanceMaximum(AUD_Handle* handle, float distance)
01495 {
01496         lock();
01497         bool result = isValid(handle);
01498 
01499         if(result)
01500                 alSourcef(((AUD_OpenALHandle*)handle)->source, AL_MAX_DISTANCE,
01501                                   distance);
01502 
01503         unlock();
01504         return result;
01505 }
01506 
01507 float AUD_OpenALDevice::getDistanceReference(AUD_Handle* handle)
01508 {
01509         float result = std::numeric_limits<float>::quiet_NaN();;
01510 
01511         lock();
01512 
01513         if(isValid(handle))
01514                 alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_REFERENCE_DISTANCE,
01515                                          &result);
01516 
01517         unlock();
01518         return result;
01519 }
01520 
01521 bool AUD_OpenALDevice::setDistanceReference(AUD_Handle* handle, float distance)
01522 {
01523         lock();
01524         bool result = isValid(handle);
01525 
01526         if(result)
01527                 alSourcef(((AUD_OpenALHandle*)handle)->source, AL_REFERENCE_DISTANCE,
01528                                   distance);
01529 
01530         unlock();
01531         return result;
01532 }
01533 
01534 float AUD_OpenALDevice::getAttenuation(AUD_Handle* handle)
01535 {
01536         float result = std::numeric_limits<float>::quiet_NaN();;
01537 
01538         lock();
01539 
01540         if(isValid(handle))
01541                 alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_ROLLOFF_FACTOR,
01542                                          &result);
01543 
01544         unlock();
01545         return result;
01546 }
01547 
01548 bool AUD_OpenALDevice::setAttenuation(AUD_Handle* handle, float factor)
01549 {
01550         lock();
01551         bool result = isValid(handle);
01552 
01553         if(result)
01554                 alSourcef(((AUD_OpenALHandle*)handle)->source, AL_ROLLOFF_FACTOR,
01555                                   factor);
01556 
01557         unlock();
01558         return result;
01559 }
01560 
01561 float AUD_OpenALDevice::getConeAngleOuter(AUD_Handle* handle)
01562 {
01563         float result = std::numeric_limits<float>::quiet_NaN();;
01564 
01565         lock();
01566 
01567         if(isValid(handle))
01568                 alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_CONE_OUTER_ANGLE,
01569                                          &result);
01570 
01571         unlock();
01572         return result;
01573 }
01574 
01575 bool AUD_OpenALDevice::setConeAngleOuter(AUD_Handle* handle, float angle)
01576 {
01577         lock();
01578         bool result = isValid(handle);
01579 
01580         if(result)
01581                 alSourcef(((AUD_OpenALHandle*)handle)->source, AL_CONE_OUTER_ANGLE,
01582                                   angle);
01583 
01584         unlock();
01585         return result;
01586 }
01587 
01588 float AUD_OpenALDevice::getConeAngleInner(AUD_Handle* handle)
01589 {
01590         float result = std::numeric_limits<float>::quiet_NaN();;
01591 
01592         lock();
01593 
01594         if(isValid(handle))
01595                 alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_CONE_INNER_ANGLE,
01596                                          &result);
01597 
01598         unlock();
01599         return result;
01600 }
01601 
01602 bool AUD_OpenALDevice::setConeAngleInner(AUD_Handle* handle, float angle)
01603 {
01604         lock();
01605         bool result = isValid(handle);
01606 
01607         if(result)
01608                 alSourcef(((AUD_OpenALHandle*)handle)->source, AL_CONE_INNER_ANGLE,
01609                                   angle);
01610 
01611         unlock();
01612         return result;
01613 }
01614 
01615 float AUD_OpenALDevice::getConeVolumeOuter(AUD_Handle* handle)
01616 {
01617         float result = std::numeric_limits<float>::quiet_NaN();;
01618 
01619         lock();
01620 
01621         if(isValid(handle))
01622                 alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_CONE_OUTER_GAIN,
01623                                          &result);
01624 
01625         unlock();
01626         return result;
01627 }
01628 
01629 bool AUD_OpenALDevice::setConeVolumeOuter(AUD_Handle* handle, float volume)
01630 {
01631         lock();
01632         bool result = isValid(handle);
01633 
01634         if(result)
01635                 alSourcef(((AUD_OpenALHandle*)handle)->source, AL_CONE_OUTER_GAIN,
01636                                   volume);
01637 
01638         unlock();
01639         return result;
01640 }