diff Alc/ALc.c @ 0:f9476ff7637e

initial forking of open-al to create multiple listeners
author Robert McIntyre <rlm@mit.edu>
date Tue, 25 Oct 2011 13:02:31 -0700
parents
children 96298d83959c
line wrap: on
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/Alc/ALc.c	Tue Oct 25 13:02:31 2011 -0700
     1.3 @@ -0,0 +1,2681 @@
     1.4 +/**
     1.5 + * OpenAL cross platform audio library
     1.6 + * Copyright (C) 1999-2007 by authors.
     1.7 + * This library is free software; you can redistribute it and/or
     1.8 + *  modify it under the terms of the GNU Library General Public
     1.9 + *  License as published by the Free Software Foundation; either
    1.10 + *  version 2 of the License, or (at your option) any later version.
    1.11 + *
    1.12 + * This library is distributed in the hope that it will be useful,
    1.13 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.14 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    1.15 + *  Library General Public License for more details.
    1.16 + *
    1.17 + * You should have received a copy of the GNU Library General Public
    1.18 + *  License along with this library; if not, write to the
    1.19 + *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    1.20 + *  Boston, MA  02111-1307, USA.
    1.21 + * Or go to http://www.gnu.org/copyleft/lgpl.html
    1.22 + */
    1.23 +
    1.24 +#include "config.h"
    1.25 +
    1.26 +#include <math.h>
    1.27 +#include <stdlib.h>
    1.28 +#include <stdio.h>
    1.29 +#include <memory.h>
    1.30 +#include <ctype.h>
    1.31 +
    1.32 +#include "alMain.h"
    1.33 +#include "alSource.h"
    1.34 +#include "AL/al.h"
    1.35 +#include "AL/alc.h"
    1.36 +#include "alThunk.h"
    1.37 +#include "alSource.h"
    1.38 +#include "alBuffer.h"
    1.39 +#include "alAuxEffectSlot.h"
    1.40 +#include "bs2b.h"
    1.41 +#include "alu.h"
    1.42 +
    1.43 +// RLM: try to include the file here.
    1.44 +
    1.45 +
    1.46 +
    1.47 +#define EmptyFuncs { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
    1.48 +static struct BackendInfo BackendList[] = {
    1.49 +#ifdef HAVE_PULSEAUDIO
    1.50 +    { "pulse", alc_pulse_init, alc_pulse_deinit, alc_pulse_probe, EmptyFuncs },
    1.51 +#endif
    1.52 +#ifdef HAVE_ALSA
    1.53 +    { "alsa", alc_alsa_init, alc_alsa_deinit, alc_alsa_probe, EmptyFuncs },
    1.54 +#endif
    1.55 +#ifdef HAVE_COREAUDIO
    1.56 +    { "core", alc_ca_init, alc_ca_deinit, alc_ca_probe, EmptyFuncs },
    1.57 +#endif
    1.58 +#ifdef HAVE_OSS
    1.59 +    { "oss", alc_oss_init, alc_oss_deinit, alc_oss_probe, EmptyFuncs },
    1.60 +#endif
    1.61 +#ifdef HAVE_SOLARIS
    1.62 +    { "solaris", alc_solaris_init, alc_solaris_deinit, alc_solaris_probe, EmptyFuncs },
    1.63 +#endif
    1.64 +#ifdef HAVE_SNDIO
    1.65 +    { "sndio", alc_sndio_init, alc_sndio_deinit, alc_sndio_probe, EmptyFuncs },
    1.66 +#endif
    1.67 +#ifdef HAVE_MMDEVAPI
    1.68 +    { "mmdevapi", alcMMDevApiInit, alcMMDevApiDeinit, alcMMDevApiProbe, EmptyFuncs },
    1.69 +#endif
    1.70 +#ifdef HAVE_DSOUND
    1.71 +    { "dsound", alcDSoundInit, alcDSoundDeinit, alcDSoundProbe, EmptyFuncs },
    1.72 +#endif
    1.73 +#ifdef HAVE_WINMM
    1.74 +    { "winmm", alcWinMMInit, alcWinMMDeinit, alcWinMMProbe, EmptyFuncs },
    1.75 +#endif
    1.76 +#ifdef HAVE_PORTAUDIO
    1.77 +    { "port", alc_pa_init, alc_pa_deinit, alc_pa_probe, EmptyFuncs },
    1.78 +#endif
    1.79 +#ifdef HAVE_OPENSL
    1.80 +    { "opensl", alc_opensl_init, alc_opensl_deinit, alc_opensl_probe, EmptyFuncs },
    1.81 +#endif
    1.82 +
    1.83 +    { "null", alc_null_init, alc_null_deinit, alc_null_probe, EmptyFuncs },
    1.84 +#ifdef HAVE_WAVE
    1.85 +    { "wave", alc_wave_init, alc_wave_deinit, alc_wave_probe, EmptyFuncs },
    1.86 +#endif
    1.87 +    { "send", alc_send_init, alc_send_deinit, alc_send_probe, EmptyFuncs },
    1.88 +    // this entry is so that the list is terminated by a "null" object,
    1.89 +    // and helps things to tell when they've reached the end of the list.
    1.90 +    { NULL, NULL, NULL, NULL, EmptyFuncs }
    1.91 +};
    1.92 +static struct BackendInfo BackendLoopback = {
    1.93 +    "loopback", alc_loopback_init, alc_loopback_deinit, alc_loopback_probe, EmptyFuncs
    1.94 +};
    1.95 +#undef EmptyFuncs
    1.96 +
    1.97 +static struct BackendInfo PlaybackBackend;
    1.98 +static struct BackendInfo CaptureBackend;
    1.99 +
   1.100 +///////////////////////////////////////////////////////
   1.101 +// STRING and EXTENSIONS
   1.102 +
   1.103 +typedef struct ALCfunction {
   1.104 +    const ALCchar *funcName;
   1.105 +    ALCvoid *address;
   1.106 +} ALCfunction;
   1.107 +
   1.108 +typedef struct ALCenums {
   1.109 +    const ALCchar *enumName;
   1.110 +    ALCenum value;
   1.111 +} ALCenums;
   1.112 +
   1.113 +
   1.114 +static const ALCfunction alcFunctions[] = {
   1.115 +    { "alcCreateContext",           (ALCvoid *) alcCreateContext         },
   1.116 +    { "alcMakeContextCurrent",      (ALCvoid *) alcMakeContextCurrent    },
   1.117 +    { "alcProcessContext",          (ALCvoid *) alcProcessContext        },
   1.118 +    { "alcSuspendContext",          (ALCvoid *) alcSuspendContext        },
   1.119 +    { "alcDestroyContext",          (ALCvoid *) alcDestroyContext        },
   1.120 +    { "alcGetCurrentContext",       (ALCvoid *) alcGetCurrentContext     },
   1.121 +    { "alcGetContextsDevice",       (ALCvoid *) alcGetContextsDevice     },
   1.122 +    { "alcOpenDevice",              (ALCvoid *) alcOpenDevice            },
   1.123 +    { "alcCloseDevice",             (ALCvoid *) alcCloseDevice           },
   1.124 +    { "alcGetError",                (ALCvoid *) alcGetError              },
   1.125 +    { "alcIsExtensionPresent",      (ALCvoid *) alcIsExtensionPresent    },
   1.126 +    { "alcGetProcAddress",          (ALCvoid *) alcGetProcAddress        },
   1.127 +    { "alcGetEnumValue",            (ALCvoid *) alcGetEnumValue          },
   1.128 +    { "alcGetString",               (ALCvoid *) alcGetString             },
   1.129 +    { "alcGetIntegerv",             (ALCvoid *) alcGetIntegerv           },
   1.130 +    { "alcCaptureOpenDevice",       (ALCvoid *) alcCaptureOpenDevice     },
   1.131 +    { "alcCaptureCloseDevice",      (ALCvoid *) alcCaptureCloseDevice    },
   1.132 +    { "alcCaptureStart",            (ALCvoid *) alcCaptureStart          },
   1.133 +    { "alcCaptureStop",             (ALCvoid *) alcCaptureStop           },
   1.134 +    { "alcCaptureSamples",          (ALCvoid *) alcCaptureSamples        },
   1.135 +
   1.136 +    { "alcSetThreadContext",        (ALCvoid *) alcSetThreadContext      },
   1.137 +    { "alcGetThreadContext",        (ALCvoid *) alcGetThreadContext      },
   1.138 +
   1.139 +    { "alcLoopbackOpenDeviceSOFT",  (ALCvoid *) alcLoopbackOpenDeviceSOFT},
   1.140 +    { "alcIsRenderFormatSupportedSOFT",(ALCvoid *) alcIsRenderFormatSupportedSOFT},
   1.141 +    { "alcRenderSamplesSOFT",       (ALCvoid *) alcRenderSamplesSOFT         },
   1.142 +
   1.143 +    { "alEnable",                   (ALCvoid *) alEnable                 },
   1.144 +    { "alDisable",                  (ALCvoid *) alDisable                },
   1.145 +    { "alIsEnabled",                (ALCvoid *) alIsEnabled              },
   1.146 +    { "alGetString",                (ALCvoid *) alGetString              },
   1.147 +    { "alGetBooleanv",              (ALCvoid *) alGetBooleanv            },
   1.148 +    { "alGetIntegerv",              (ALCvoid *) alGetIntegerv            },
   1.149 +    { "alGetFloatv",                (ALCvoid *) alGetFloatv              },
   1.150 +    { "alGetDoublev",               (ALCvoid *) alGetDoublev             },
   1.151 +    { "alGetBoolean",               (ALCvoid *) alGetBoolean             },
   1.152 +    { "alGetInteger",               (ALCvoid *) alGetInteger             },
   1.153 +    { "alGetFloat",                 (ALCvoid *) alGetFloat               },
   1.154 +    { "alGetDouble",                (ALCvoid *) alGetDouble              },
   1.155 +    { "alGetError",                 (ALCvoid *) alGetError               },
   1.156 +    { "alIsExtensionPresent",       (ALCvoid *) alIsExtensionPresent     },
   1.157 +    { "alGetProcAddress",           (ALCvoid *) alGetProcAddress         },
   1.158 +    { "alGetEnumValue",             (ALCvoid *) alGetEnumValue           },
   1.159 +    { "alListenerf",                (ALCvoid *) alListenerf              },
   1.160 +    { "alListener3f",               (ALCvoid *) alListener3f             },
   1.161 +    { "alListenerfv",               (ALCvoid *) alListenerfv             },
   1.162 +    { "alListeneri",                (ALCvoid *) alListeneri              },
   1.163 +    { "alListener3i",               (ALCvoid *) alListener3i             },
   1.164 +    { "alListeneriv",               (ALCvoid *) alListeneriv             },
   1.165 +    { "alGetListenerf",             (ALCvoid *) alGetListenerf           },
   1.166 +    { "alGetListener3f",            (ALCvoid *) alGetListener3f          },
   1.167 +    { "alGetListenerfv",            (ALCvoid *) alGetListenerfv          },
   1.168 +    { "alGetListeneri",             (ALCvoid *) alGetListeneri           },
   1.169 +    { "alGetListener3i",            (ALCvoid *) alGetListener3i          },
   1.170 +    { "alGetListeneriv",            (ALCvoid *) alGetListeneriv          },
   1.171 +    { "alGenSources",               (ALCvoid *) alGenSources             },
   1.172 +    { "alDeleteSources",            (ALCvoid *) alDeleteSources          },
   1.173 +    { "alIsSource",                 (ALCvoid *) alIsSource               },
   1.174 +    { "alSourcef",                  (ALCvoid *) alSourcef                },
   1.175 +    { "alSource3f",                 (ALCvoid *) alSource3f               },
   1.176 +    { "alSourcefv",                 (ALCvoid *) alSourcefv               },
   1.177 +    { "alSourcei",                  (ALCvoid *) alSourcei                },
   1.178 +    { "alSource3i",                 (ALCvoid *) alSource3i               },
   1.179 +    { "alSourceiv",                 (ALCvoid *) alSourceiv               },
   1.180 +    { "alGetSourcef",               (ALCvoid *) alGetSourcef             },
   1.181 +    { "alGetSource3f",              (ALCvoid *) alGetSource3f            },
   1.182 +    { "alGetSourcefv",              (ALCvoid *) alGetSourcefv            },
   1.183 +    { "alGetSourcei",               (ALCvoid *) alGetSourcei             },
   1.184 +    { "alGetSource3i",              (ALCvoid *) alGetSource3i            },
   1.185 +    { "alGetSourceiv",              (ALCvoid *) alGetSourceiv            },
   1.186 +    { "alSourcePlayv",              (ALCvoid *) alSourcePlayv            },
   1.187 +    { "alSourceStopv",              (ALCvoid *) alSourceStopv            },
   1.188 +    { "alSourceRewindv",            (ALCvoid *) alSourceRewindv          },
   1.189 +    { "alSourcePausev",             (ALCvoid *) alSourcePausev           },
   1.190 +    { "alSourcePlay",               (ALCvoid *) alSourcePlay             },
   1.191 +    { "alSourceStop",               (ALCvoid *) alSourceStop             },
   1.192 +    { "alSourceRewind",             (ALCvoid *) alSourceRewind           },
   1.193 +    { "alSourcePause",              (ALCvoid *) alSourcePause            },
   1.194 +    { "alSourceQueueBuffers",       (ALCvoid *) alSourceQueueBuffers     },
   1.195 +    { "alSourceUnqueueBuffers",     (ALCvoid *) alSourceUnqueueBuffers   },
   1.196 +    { "alGenBuffers",               (ALCvoid *) alGenBuffers             },
   1.197 +    { "alDeleteBuffers",            (ALCvoid *) alDeleteBuffers          },
   1.198 +    { "alIsBuffer",                 (ALCvoid *) alIsBuffer               },
   1.199 +    { "alBufferData",               (ALCvoid *) alBufferData             },
   1.200 +    { "alBufferf",                  (ALCvoid *) alBufferf                },
   1.201 +    { "alBuffer3f",                 (ALCvoid *) alBuffer3f               },
   1.202 +    { "alBufferfv",                 (ALCvoid *) alBufferfv               },
   1.203 +    { "alBufferi",                  (ALCvoid *) alBufferi                },
   1.204 +    { "alBuffer3i",                 (ALCvoid *) alBuffer3i               },
   1.205 +    { "alBufferiv",                 (ALCvoid *) alBufferiv               },
   1.206 +    { "alGetBufferf",               (ALCvoid *) alGetBufferf             },
   1.207 +    { "alGetBuffer3f",              (ALCvoid *) alGetBuffer3f            },
   1.208 +    { "alGetBufferfv",              (ALCvoid *) alGetBufferfv            },
   1.209 +    { "alGetBufferi",               (ALCvoid *) alGetBufferi             },
   1.210 +    { "alGetBuffer3i",              (ALCvoid *) alGetBuffer3i            },
   1.211 +    { "alGetBufferiv",              (ALCvoid *) alGetBufferiv            },
   1.212 +    { "alDopplerFactor",            (ALCvoid *) alDopplerFactor          },
   1.213 +    { "alDopplerVelocity",          (ALCvoid *) alDopplerVelocity        },
   1.214 +    { "alSpeedOfSound",             (ALCvoid *) alSpeedOfSound           },
   1.215 +    { "alDistanceModel",            (ALCvoid *) alDistanceModel          },
   1.216 +
   1.217 +    { "alGenFilters",               (ALCvoid *) alGenFilters             },
   1.218 +    { "alDeleteFilters",            (ALCvoid *) alDeleteFilters          },
   1.219 +    { "alIsFilter",                 (ALCvoid *) alIsFilter               },
   1.220 +    { "alFilteri",                  (ALCvoid *) alFilteri                },
   1.221 +    { "alFilteriv",                 (ALCvoid *) alFilteriv               },
   1.222 +    { "alFilterf",                  (ALCvoid *) alFilterf                },
   1.223 +    { "alFilterfv",                 (ALCvoid *) alFilterfv               },
   1.224 +    { "alGetFilteri",               (ALCvoid *) alGetFilteri             },
   1.225 +    { "alGetFilteriv",              (ALCvoid *) alGetFilteriv            },
   1.226 +    { "alGetFilterf",               (ALCvoid *) alGetFilterf             },
   1.227 +    { "alGetFilterfv",              (ALCvoid *) alGetFilterfv            },
   1.228 +    { "alGenEffects",               (ALCvoid *) alGenEffects             },
   1.229 +    { "alDeleteEffects",            (ALCvoid *) alDeleteEffects          },
   1.230 +    { "alIsEffect",                 (ALCvoid *) alIsEffect               },
   1.231 +    { "alEffecti",                  (ALCvoid *) alEffecti                },
   1.232 +    { "alEffectiv",                 (ALCvoid *) alEffectiv               },
   1.233 +    { "alEffectf",                  (ALCvoid *) alEffectf                },
   1.234 +    { "alEffectfv",                 (ALCvoid *) alEffectfv               },
   1.235 +    { "alGetEffecti",               (ALCvoid *) alGetEffecti             },
   1.236 +    { "alGetEffectiv",              (ALCvoid *) alGetEffectiv            },
   1.237 +    { "alGetEffectf",               (ALCvoid *) alGetEffectf             },
   1.238 +    { "alGetEffectfv",              (ALCvoid *) alGetEffectfv            },
   1.239 +    { "alGenAuxiliaryEffectSlots",  (ALCvoid *) alGenAuxiliaryEffectSlots},
   1.240 +    { "alDeleteAuxiliaryEffectSlots",(ALCvoid *) alDeleteAuxiliaryEffectSlots},
   1.241 +    { "alIsAuxiliaryEffectSlot",    (ALCvoid *) alIsAuxiliaryEffectSlot  },
   1.242 +    { "alAuxiliaryEffectSloti",     (ALCvoid *) alAuxiliaryEffectSloti   },
   1.243 +    { "alAuxiliaryEffectSlotiv",    (ALCvoid *) alAuxiliaryEffectSlotiv  },
   1.244 +    { "alAuxiliaryEffectSlotf",     (ALCvoid *) alAuxiliaryEffectSlotf   },
   1.245 +    { "alAuxiliaryEffectSlotfv",    (ALCvoid *) alAuxiliaryEffectSlotfv  },
   1.246 +    { "alGetAuxiliaryEffectSloti",  (ALCvoid *) alGetAuxiliaryEffectSloti},
   1.247 +    { "alGetAuxiliaryEffectSlotiv", (ALCvoid *) alGetAuxiliaryEffectSlotiv},
   1.248 +    { "alGetAuxiliaryEffectSlotf",  (ALCvoid *) alGetAuxiliaryEffectSlotf},
   1.249 +    { "alGetAuxiliaryEffectSlotfv", (ALCvoid *) alGetAuxiliaryEffectSlotfv},
   1.250 +
   1.251 +    { "alBufferSubDataSOFT",        (ALCvoid *) alBufferSubDataSOFT      },
   1.252 +
   1.253 +    { "alBufferSamplesSOFT",        (ALCvoid *) alBufferSamplesSOFT      },
   1.254 +    { "alBufferSubSamplesSOFT",     (ALCvoid *) alBufferSubSamplesSOFT   },
   1.255 +    { "alGetBufferSamplesSOFT",     (ALCvoid *) alGetBufferSamplesSOFT   },
   1.256 +    { "alIsBufferFormatSupportedSOFT",(ALCvoid *) alIsBufferFormatSupportedSOFT},
   1.257 +
   1.258 +    { "alDeferUpdatesSOFT",         (ALCvoid *) alDeferUpdatesSOFT       },
   1.259 +    { "alProcessUpdatesSOFT",       (ALCvoid *) alProcessUpdatesSOFT     },
   1.260 +
   1.261 +    { NULL,                         (ALCvoid *) NULL                     }
   1.262 +};
   1.263 +
   1.264 +static const ALCenums enumeration[] = {
   1.265 +    // Types
   1.266 +    { "ALC_INVALID",                          ALC_INVALID                         },
   1.267 +    { "ALC_FALSE",                            ALC_FALSE                           },
   1.268 +    { "ALC_TRUE",                             ALC_TRUE                            },
   1.269 +
   1.270 +    // ALC Properties
   1.271 +    { "ALC_MAJOR_VERSION",                    ALC_MAJOR_VERSION                   },
   1.272 +    { "ALC_MINOR_VERSION",                    ALC_MINOR_VERSION                   },
   1.273 +    { "ALC_ATTRIBUTES_SIZE",                  ALC_ATTRIBUTES_SIZE                 },
   1.274 +    { "ALC_ALL_ATTRIBUTES",                   ALC_ALL_ATTRIBUTES                  },
   1.275 +    { "ALC_DEFAULT_DEVICE_SPECIFIER",         ALC_DEFAULT_DEVICE_SPECIFIER        },
   1.276 +    { "ALC_DEVICE_SPECIFIER",                 ALC_DEVICE_SPECIFIER                },
   1.277 +    { "ALC_ALL_DEVICES_SPECIFIER",            ALC_ALL_DEVICES_SPECIFIER           },
   1.278 +    { "ALC_DEFAULT_ALL_DEVICES_SPECIFIER",    ALC_DEFAULT_ALL_DEVICES_SPECIFIER   },
   1.279 +    { "ALC_EXTENSIONS",                       ALC_EXTENSIONS                      },
   1.280 +    { "ALC_FREQUENCY",                        ALC_FREQUENCY                       },
   1.281 +    { "ALC_REFRESH",                          ALC_REFRESH                         },
   1.282 +    { "ALC_SYNC",                             ALC_SYNC                            },
   1.283 +    { "ALC_MONO_SOURCES",                     ALC_MONO_SOURCES                    },
   1.284 +    { "ALC_STEREO_SOURCES",                   ALC_STEREO_SOURCES                  },
   1.285 +    { "ALC_CAPTURE_DEVICE_SPECIFIER",         ALC_CAPTURE_DEVICE_SPECIFIER        },
   1.286 +    { "ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER", ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER},
   1.287 +    { "ALC_CAPTURE_SAMPLES",                  ALC_CAPTURE_SAMPLES                 },
   1.288 +    { "ALC_CONNECTED",                        ALC_CONNECTED                       },
   1.289 +
   1.290 +    // EFX Properties
   1.291 +    { "ALC_EFX_MAJOR_VERSION",                ALC_EFX_MAJOR_VERSION               },
   1.292 +    { "ALC_EFX_MINOR_VERSION",                ALC_EFX_MINOR_VERSION               },
   1.293 +    { "ALC_MAX_AUXILIARY_SENDS",              ALC_MAX_AUXILIARY_SENDS             },
   1.294 +
   1.295 +    // Loopback device Properties
   1.296 +    { "ALC_FORMAT_CHANNELS_SOFT",             ALC_FORMAT_CHANNELS_SOFT            },
   1.297 +    { "ALC_FORMAT_TYPE_SOFT",                 ALC_FORMAT_TYPE_SOFT                },
   1.298 +
   1.299 +    // Buffer Channel Configurations
   1.300 +    { "ALC_MONO",                             ALC_MONO                            },
   1.301 +    { "ALC_STEREO",                           ALC_STEREO                          },
   1.302 +    { "ALC_QUAD",                             ALC_QUAD                            },
   1.303 +    { "ALC_5POINT1",                          ALC_5POINT1                         },
   1.304 +    { "ALC_6POINT1",                          ALC_6POINT1                         },
   1.305 +    { "ALC_7POINT1",                          ALC_7POINT1                         },
   1.306 +
   1.307 +    // Buffer Sample Types
   1.308 +    { "ALC_BYTE",                             ALC_BYTE                            },
   1.309 +    { "ALC_UNSIGNED_BYTE",                    ALC_UNSIGNED_BYTE                   },
   1.310 +    { "ALC_SHORT",                            ALC_SHORT                           },
   1.311 +    { "ALC_UNSIGNED_SHORT",                   ALC_UNSIGNED_SHORT                  },
   1.312 +    { "ALC_INT",                              ALC_INT                             },
   1.313 +    { "ALC_UNSIGNED_INT",                     ALC_UNSIGNED_INT                    },
   1.314 +    { "ALC_FLOAT",                            ALC_FLOAT                           },
   1.315 +
   1.316 +    // ALC Error Message
   1.317 +    { "ALC_NO_ERROR",                         ALC_NO_ERROR                        },
   1.318 +    { "ALC_INVALID_DEVICE",                   ALC_INVALID_DEVICE                  },
   1.319 +    { "ALC_INVALID_CONTEXT",                  ALC_INVALID_CONTEXT                 },
   1.320 +    { "ALC_INVALID_ENUM",                     ALC_INVALID_ENUM                    },
   1.321 +    { "ALC_INVALID_VALUE",                    ALC_INVALID_VALUE                   },
   1.322 +    { "ALC_OUT_OF_MEMORY",                    ALC_OUT_OF_MEMORY                   },
   1.323 +
   1.324 +    { NULL,                                   (ALCenum)0 }
   1.325 +};
   1.326 +// Error strings
   1.327 +static const ALCchar alcNoError[] = "No Error";
   1.328 +static const ALCchar alcErrInvalidDevice[] = "Invalid Device";
   1.329 +static const ALCchar alcErrInvalidContext[] = "Invalid Context";
   1.330 +static const ALCchar alcErrInvalidEnum[] = "Invalid Enum";
   1.331 +static const ALCchar alcErrInvalidValue[] = "Invalid Value";
   1.332 +static const ALCchar alcErrOutOfMemory[] = "Out of Memory";
   1.333 +
   1.334 +/* Device lists. Sizes only include the first ending null character, not the
   1.335 + * second */
   1.336 +static ALCchar *alcDeviceList;
   1.337 +static size_t alcDeviceListSize;
   1.338 +static ALCchar *alcAllDeviceList;
   1.339 +static size_t alcAllDeviceListSize;
   1.340 +static ALCchar *alcCaptureDeviceList;
   1.341 +static size_t alcCaptureDeviceListSize;
   1.342 +/* Default is always the first in the list */
   1.343 +static ALCchar *alcDefaultDeviceSpecifier;
   1.344 +static ALCchar *alcDefaultAllDeviceSpecifier;
   1.345 +static ALCchar *alcCaptureDefaultDeviceSpecifier;
   1.346 +
   1.347 +
   1.348 +static const ALCchar alcNoDeviceExtList[] =
   1.349 +    "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
   1.350 +    "ALC_EXT_thread_local_context ALC_SOFTX_loopback_device";
   1.351 +static const ALCchar alcExtensionList[] =
   1.352 +    "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
   1.353 +    "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
   1.354 +    "ALC_EXT_thread_local_context ALC_SOFTX_loopback_device";
   1.355 +static const ALCint alcMajorVersion = 1;
   1.356 +static const ALCint alcMinorVersion = 1;
   1.357 +
   1.358 +static const ALCint alcEFXMajorVersion = 1;
   1.359 +static const ALCint alcEFXMinorVersion = 0;
   1.360 +
   1.361 +///////////////////////////////////////////////////////
   1.362 +
   1.363 +
   1.364 +///////////////////////////////////////////////////////
   1.365 +// Global Variables
   1.366 +
   1.367 +static CRITICAL_SECTION ListLock;
   1.368 +
   1.369 +/* Device List */
   1.370 +static ALCdevice *g_pDeviceList = NULL;
   1.371 +static ALCuint    g_ulDeviceCount = 0;
   1.372 +
   1.373 +// Context List
   1.374 +static ALCcontext *g_pContextList = NULL;
   1.375 +static ALCuint     g_ulContextCount = 0;
   1.376 +
   1.377 +// Thread-local current context
   1.378 +static tls_type LocalContext;
   1.379 +// Process-wide current context
   1.380 +static ALCcontext *GlobalContext;
   1.381 +
   1.382 +// Context Error
   1.383 +static ALCenum g_eLastNullDeviceError = ALC_NO_ERROR;
   1.384 +
   1.385 +// Default context extensions
   1.386 +static const ALchar alExtList[] =
   1.387 +    "AL_EXT_DOUBLE AL_EXT_EXPONENT_DISTANCE AL_EXT_FLOAT32 AL_EXT_IMA4 "
   1.388 +    "AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS AL_EXT_MULAW "
   1.389 +    "AL_EXT_MULAW_MCFORMATS AL_EXT_OFFSET AL_EXT_source_distance_model "
   1.390 +    "AL_LOKI_quadriphonic AL_SOFTX_buffer_samples AL_SOFT_buffer_sub_data "
   1.391 +    "AL_SOFTX_deferred_updates AL_SOFT_loop_points "
   1.392 +    "AL_SOFTX_non_virtual_channels";
   1.393 +
   1.394 +// Mixing Priority Level
   1.395 +ALint RTPrioLevel;
   1.396 +
   1.397 +// Output Log File
   1.398 +FILE *LogFile;
   1.399 +
   1.400 +// Output Log Level
   1.401 +#ifdef _DEBUG
   1.402 +enum LogLevel LogLevel = LogWarning;
   1.403 +#else
   1.404 +enum LogLevel LogLevel = LogError;
   1.405 +#endif
   1.406 +
   1.407 +// Cone scalar
   1.408 +ALdouble ConeScale = 0.5;
   1.409 +
   1.410 +// Localized Z scalar for mono sources
   1.411 +ALdouble ZScale = 1.0;
   1.412 +
   1.413 +/* One-time configuration init control */
   1.414 +static pthread_once_t alc_config_once = PTHREAD_ONCE_INIT;
   1.415 +
   1.416 +///////////////////////////////////////////////////////
   1.417 +
   1.418 +
   1.419 +///////////////////////////////////////////////////////
   1.420 +// ALC Related helper functions
   1.421 +static void ReleaseALC(ALCboolean doclose);
   1.422 +
   1.423 +static void alc_initconfig(void);
   1.424 +#define DO_INITCONFIG() pthread_once(&alc_config_once, alc_initconfig)
   1.425 +
   1.426 +#if defined(_WIN32)
   1.427 +static void alc_init(void);
   1.428 +static void alc_deinit(void);
   1.429 +static void alc_deinit_safe(void);
   1.430 +
   1.431 +#ifndef AL_LIBTYPE_STATIC
   1.432 +BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
   1.433 +{
   1.434 +    // Perform actions based on the reason for calling.
   1.435 +    switch(ul_reason_for_call)
   1.436 +    {
   1.437 +        case DLL_PROCESS_ATTACH:
   1.438 +            DisableThreadLibraryCalls(hModule);
   1.439 +            alc_init();
   1.440 +            break;
   1.441 +
   1.442 +        case DLL_PROCESS_DETACH:
   1.443 +            if(!lpReserved)
   1.444 +                alc_deinit();
   1.445 +            else
   1.446 +                alc_deinit_safe();
   1.447 +            break;
   1.448 +    }
   1.449 +    return TRUE;
   1.450 +}
   1.451 +#elif defined(_MSC_VER)
   1.452 +#pragma section(".CRT$XCU",read)
   1.453 +static void alc_constructor(void);
   1.454 +static void alc_destructor(void);
   1.455 +__declspec(allocate(".CRT$XCU")) void (__cdecl* alc_constructor_)(void) = alc_constructor;
   1.456 +
   1.457 +static void alc_constructor(void)
   1.458 +{
   1.459 +    atexit(alc_destructor);
   1.460 +    alc_init();
   1.461 +}
   1.462 +
   1.463 +static void alc_destructor(void)
   1.464 +{
   1.465 +    alc_deinit();
   1.466 +}
   1.467 +#elif defined(HAVE_GCC_DESTRUCTOR)
   1.468 +static void alc_init(void) __attribute__((constructor));
   1.469 +static void alc_deinit(void) __attribute__((destructor));
   1.470 +#else
   1.471 +#error "No static initialization available on this platform!"
   1.472 +#endif
   1.473 +#elif defined(HAVE_GCC_DESTRUCTOR)
   1.474 +static void alc_init(void) __attribute__((constructor));
   1.475 +static void alc_deinit(void) __attribute__((destructor));
   1.476 +#else
   1.477 +#error "No global initialization available on this platform!"
   1.478 +#endif
   1.479 +
   1.480 +static void alc_init(void)
   1.481 +{
   1.482 +    const char *str;
   1.483 +
   1.484 +    LogFile = stderr;
   1.485 +
   1.486 +    str = getenv("__ALSOFT_HALF_ANGLE_CONES");
   1.487 +    if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
   1.488 +        ConeScale = 1.0;
   1.489 +
   1.490 +    str = getenv("__ALSOFT_REVERSE_Z");
   1.491 +    if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
   1.492 +        ZScale = -1.0;
   1.493 +
   1.494 +    tls_create(&LocalContext);
   1.495 +    InitializeCriticalSection(&ListLock);
   1.496 +    ThunkInit();
   1.497 +}
   1.498 +
   1.499 +static void alc_deinit_safe(void)
   1.500 +{
   1.501 +    ReleaseALC(ALC_FALSE);
   1.502 +
   1.503 +    FreeALConfig();
   1.504 +
   1.505 +    ThunkExit();
   1.506 +    DeleteCriticalSection(&ListLock);
   1.507 +    tls_delete(LocalContext);
   1.508 +
   1.509 +    if(LogFile != stderr)
   1.510 +        fclose(LogFile);
   1.511 +    LogFile = NULL;
   1.512 +}
   1.513 +
   1.514 +static void alc_deinit(void)
   1.515 +{
   1.516 +    int i;
   1.517 +
   1.518 +    ReleaseALC(ALC_TRUE);
   1.519 +
   1.520 +    memset(&PlaybackBackend, 0, sizeof(PlaybackBackend));
   1.521 +    memset(&CaptureBackend, 0, sizeof(CaptureBackend));
   1.522 +
   1.523 +    for(i = 0;BackendList[i].Deinit;i++)
   1.524 +        BackendList[i].Deinit();
   1.525 +    BackendLoopback.Deinit();
   1.526 +
   1.527 +    alc_deinit_safe();
   1.528 +}
   1.529 +
   1.530 +static void alc_initconfig(void)
   1.531 +{
   1.532 +  printf("OPENAL-AURELLEM: alc_init_config!!\n");
   1.533 +    const char *devs, *str;
   1.534 +    int i, n;
   1.535 +
   1.536 +    str = getenv("ALSOFT_LOGLEVEL");
   1.537 +    if(str)
   1.538 +    {
   1.539 +        long lvl = strtol(str, NULL, 0);
   1.540 +        if(lvl >= NoLog && lvl <= LogTrace)
   1.541 +            LogLevel = lvl;
   1.542 +    }
   1.543 +
   1.544 +    str = getenv("ALSOFT_LOGFILE");
   1.545 +    if(str && str[0])
   1.546 +    {
   1.547 +        FILE *logfile = fopen(str, "wat");
   1.548 +        if(logfile) LogFile = logfile;
   1.549 +        else ERR("Failed to open log file '%s'\n", str);
   1.550 +    }
   1.551 +
   1.552 +    ReadALConfig();
   1.553 +
   1.554 +    InitHrtf();
   1.555 +
   1.556 +#ifdef _WIN32
   1.557 +    RTPrioLevel = GetConfigValueInt(NULL, "rt-prio", 1);
   1.558 +#else
   1.559 +    RTPrioLevel = GetConfigValueInt(NULL, "rt-prio", 0);
   1.560 +#endif
   1.561 +
   1.562 +    DefaultResampler = GetConfigValueInt(NULL, "resampler", RESAMPLER_DEFAULT);
   1.563 +    if(DefaultResampler >= RESAMPLER_MAX || DefaultResampler <= RESAMPLER_MIN)
   1.564 +        DefaultResampler = RESAMPLER_DEFAULT;
   1.565 +
   1.566 +    ReverbBoost *= aluPow(10.0f, GetConfigValueFloat("reverb", "boost", 0.0f) /
   1.567 +                                 20.0f);
   1.568 +    EmulateEAXReverb = GetConfigValueBool("reverb", "emulate-eax", AL_FALSE);
   1.569 +
   1.570 +    devs = GetConfigValue(NULL, "drivers", "");
   1.571 +    //printf("these are the devices: %s\n", devs);
   1.572 +
   1.573 +    if(devs[0])
   1.574 +    {
   1.575 +        int n;
   1.576 +        size_t len;
   1.577 +        const char *next = devs;
   1.578 +        int endlist, delitem;
   1.579 +
   1.580 +        i = 0;
   1.581 +        do {
   1.582 +            devs = next;
   1.583 +	    //printf("AURELLEM: devs is %s\n",devs);
   1.584 +            next = strchr(devs, ',');
   1.585 +
   1.586 +            delitem = (devs[0] == '-');
   1.587 +            if(devs[0] == '-') devs++;
   1.588 +
   1.589 +            if(!devs[0] || devs[0] == ',')
   1.590 +            {
   1.591 +                endlist = 0;
   1.592 +                continue;
   1.593 +            }
   1.594 +            endlist = 1;
   1.595 +
   1.596 +            len = (next ? ((size_t)(next-devs)) : strlen(devs));
   1.597 +            for(n = i;BackendList[n].Init;n++)
   1.598 +            {
   1.599 +	      //printf("AURELLEM: device-name -- %s\n",BackendList[n].name);
   1.600 +                if(len == strlen(BackendList[n].name) &&
   1.601 +                   strncmp(BackendList[n].name, devs, len) == 0)
   1.602 +                {
   1.603 +                    if(delitem)
   1.604 +                    {
   1.605 +                        do {
   1.606 +                            BackendList[n] = BackendList[n+1];
   1.607 +                            ++n;
   1.608 +                        } 
   1.609 +			// this relies on the last entry being terminated by an
   1.610 +			// entry with all nulls.  
   1.611 +			while(BackendList[n].Init);
   1.612 +                    }
   1.613 +                    else
   1.614 +                    {
   1.615 +                        struct BackendInfo Bkp = BackendList[n];
   1.616 +                        while(n > i)
   1.617 +                        {
   1.618 +                            BackendList[n] = BackendList[n-1];
   1.619 +                            --n;
   1.620 +                        }
   1.621 +                        BackendList[n] = Bkp;
   1.622 +
   1.623 +                        i++;
   1.624 +                    }
   1.625 +                    break;
   1.626 +                }
   1.627 +            }
   1.628 +        } while(next++);
   1.629 +
   1.630 +        if(endlist)
   1.631 +        {
   1.632 +            BackendList[i].name = NULL;
   1.633 +            BackendList[i].Init = NULL;
   1.634 +            BackendList[i].Deinit = NULL;
   1.635 +            BackendList[i].Probe = NULL;
   1.636 +        }
   1.637 +    }
   1.638 +
   1.639 +    for(i = 0;BackendList[i].Init && (!PlaybackBackend.name || !CaptureBackend.name);i++)
   1.640 +    {
   1.641 +        if(!BackendList[i].Init(&BackendList[i].Funcs))
   1.642 +        {
   1.643 +            WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name);
   1.644 +            continue;
   1.645 +        }
   1.646 +
   1.647 +        TRACE("Initialized backend \"%s\"\n", BackendList[i].name);
   1.648 +        if(BackendList[i].Funcs.OpenPlayback && !PlaybackBackend.name)
   1.649 +        {
   1.650 +            PlaybackBackend = BackendList[i];
   1.651 +            TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
   1.652 +        }
   1.653 +        if(BackendList[i].Funcs.OpenCapture && !CaptureBackend.name)
   1.654 +        {
   1.655 +            CaptureBackend = BackendList[i];
   1.656 +            TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
   1.657 +        }
   1.658 +    }
   1.659 +    BackendLoopback.Init(&BackendLoopback.Funcs);
   1.660 +
   1.661 +    str = GetConfigValue(NULL, "excludefx", "");
   1.662 +    if(str[0])
   1.663 +    {
   1.664 +        size_t len;
   1.665 +        const char *next = str;
   1.666 +
   1.667 +        do {
   1.668 +            str = next;
   1.669 +            next = strchr(str, ',');
   1.670 +
   1.671 +            if(!str[0] || next == str)
   1.672 +                continue;
   1.673 +
   1.674 +            len = (next ? ((size_t)(next-str)) : strlen(str));
   1.675 +            for(n = 0;EffectList[n].name;n++)
   1.676 +            {
   1.677 +                if(len == strlen(EffectList[n].name) &&
   1.678 +                   strncmp(EffectList[n].name, str, len) == 0)
   1.679 +                    DisabledEffects[EffectList[n].type] = AL_TRUE;
   1.680 +            }
   1.681 +        } while(next++);
   1.682 +    }
   1.683 +}
   1.684 +
   1.685 +
   1.686 +static void ProbeList(ALCchar **list, size_t *listsize, enum DevProbe type)
   1.687 +{
   1.688 +    free(*list);
   1.689 +    *list = NULL;
   1.690 +    *listsize = 0;
   1.691 +
   1.692 +    DO_INITCONFIG();
   1.693 +    if(type == CAPTURE_DEVICE_PROBE)
   1.694 +        CaptureBackend.Probe(type);
   1.695 +    else
   1.696 +        PlaybackBackend.Probe(type);
   1.697 +}
   1.698 +
   1.699 +static void ProbeDeviceList(void)
   1.700 +{ ProbeList(&alcDeviceList, &alcDeviceListSize, DEVICE_PROBE); }
   1.701 +static void ProbeAllDeviceList(void)
   1.702 +{ ProbeList(&alcAllDeviceList, &alcAllDeviceListSize, ALL_DEVICE_PROBE); }
   1.703 +static void ProbeCaptureDeviceList(void)
   1.704 +{ ProbeList(&alcCaptureDeviceList, &alcCaptureDeviceListSize, CAPTURE_DEVICE_PROBE); }
   1.705 +
   1.706 +
   1.707 +static void AppendList(const ALCchar *name, ALCchar **List, size_t *ListSize)
   1.708 +{
   1.709 +    size_t len = strlen(name);
   1.710 +    void *temp;
   1.711 +
   1.712 +    if(len == 0)
   1.713 +        return;
   1.714 +
   1.715 +    temp = realloc(*List, (*ListSize) + len + 2);
   1.716 +    if(!temp)
   1.717 +    {
   1.718 +        ERR("Realloc failed to add %s!\n", name);
   1.719 +        return;
   1.720 +    }
   1.721 +    *List = temp;
   1.722 +
   1.723 +    memcpy((*List)+(*ListSize), name, len+1);
   1.724 +    *ListSize += len+1;
   1.725 +    (*List)[*ListSize] = 0;
   1.726 +}
   1.727 +
   1.728 +#define DECL_APPEND_LIST_FUNC(type)                                          \
   1.729 +void Append##type##List(const ALCchar *name)                                 \
   1.730 +{ AppendList(name, &alc##type##List, &alc##type##ListSize); }
   1.731 +
   1.732 +DECL_APPEND_LIST_FUNC(Device)
   1.733 +DECL_APPEND_LIST_FUNC(AllDevice)
   1.734 +DECL_APPEND_LIST_FUNC(CaptureDevice)
   1.735 +
   1.736 +#undef DECL_APPEND_LIST_FUNC
   1.737 +
   1.738 +
   1.739 +/* Sets the default channel order used by most non-WaveFormatEx-based APIs */
   1.740 +void SetDefaultChannelOrder(ALCdevice *device)
   1.741 +{
   1.742 +    switch(device->FmtChans)
   1.743 +    {
   1.744 +    case DevFmtX51: device->DevChannels[0] = FRONT_LEFT;
   1.745 +                    device->DevChannels[1] = FRONT_RIGHT;
   1.746 +                    device->DevChannels[2] = BACK_LEFT;
   1.747 +                    device->DevChannels[3] = BACK_RIGHT;
   1.748 +                    device->DevChannels[4] = FRONT_CENTER;
   1.749 +                    device->DevChannels[5] = LFE;
   1.750 +                    return;
   1.751 +
   1.752 +    case DevFmtX71: device->DevChannels[0] = FRONT_LEFT;
   1.753 +                    device->DevChannels[1] = FRONT_RIGHT;
   1.754 +                    device->DevChannels[2] = BACK_LEFT;
   1.755 +                    device->DevChannels[3] = BACK_RIGHT;
   1.756 +                    device->DevChannels[4] = FRONT_CENTER;
   1.757 +                    device->DevChannels[5] = LFE;
   1.758 +                    device->DevChannels[6] = SIDE_LEFT;
   1.759 +                    device->DevChannels[7] = SIDE_RIGHT;
   1.760 +                    return;
   1.761 +
   1.762 +    /* Same as WFX order */
   1.763 +    case DevFmtMono:
   1.764 +    case DevFmtStereo:
   1.765 +    case DevFmtQuad:
   1.766 +    case DevFmtX51Side:
   1.767 +    case DevFmtX61:
   1.768 +        break;
   1.769 +    }
   1.770 +    SetDefaultWFXChannelOrder(device);
   1.771 +}
   1.772 +/* Sets the default order used by WaveFormatEx */
   1.773 +void SetDefaultWFXChannelOrder(ALCdevice *device)
   1.774 +{
   1.775 +    switch(device->FmtChans)
   1.776 +    {
   1.777 +    case DevFmtMono: device->DevChannels[0] = FRONT_CENTER; break;
   1.778 +
   1.779 +    case DevFmtStereo: device->DevChannels[0] = FRONT_LEFT;
   1.780 +                       device->DevChannels[1] = FRONT_RIGHT; break;
   1.781 +
   1.782 +    case DevFmtQuad: device->DevChannels[0] = FRONT_LEFT;
   1.783 +                     device->DevChannels[1] = FRONT_RIGHT;
   1.784 +                     device->DevChannels[2] = BACK_LEFT;
   1.785 +                     device->DevChannels[3] = BACK_RIGHT; break;
   1.786 +
   1.787 +    case DevFmtX51: device->DevChannels[0] = FRONT_LEFT;
   1.788 +                    device->DevChannels[1] = FRONT_RIGHT;
   1.789 +                    device->DevChannels[2] = FRONT_CENTER;
   1.790 +                    device->DevChannels[3] = LFE;
   1.791 +                    device->DevChannels[4] = BACK_LEFT;
   1.792 +                    device->DevChannels[5] = BACK_RIGHT; break;
   1.793 +
   1.794 +    case DevFmtX51Side: device->DevChannels[0] = FRONT_LEFT;
   1.795 +                        device->DevChannels[1] = FRONT_RIGHT;
   1.796 +                        device->DevChannels[2] = FRONT_CENTER;
   1.797 +                        device->DevChannels[3] = LFE;
   1.798 +                        device->DevChannels[4] = SIDE_LEFT;
   1.799 +                        device->DevChannels[5] = SIDE_RIGHT; break;
   1.800 +
   1.801 +    case DevFmtX61: device->DevChannels[0] = FRONT_LEFT;
   1.802 +                    device->DevChannels[1] = FRONT_RIGHT;
   1.803 +                    device->DevChannels[2] = FRONT_CENTER;
   1.804 +                    device->DevChannels[3] = LFE;
   1.805 +                    device->DevChannels[4] = BACK_CENTER;
   1.806 +                    device->DevChannels[5] = SIDE_LEFT;
   1.807 +                    device->DevChannels[6] = SIDE_RIGHT; break;
   1.808 +
   1.809 +    case DevFmtX71: device->DevChannels[0] = FRONT_LEFT;
   1.810 +                    device->DevChannels[1] = FRONT_RIGHT;
   1.811 +                    device->DevChannels[2] = FRONT_CENTER;
   1.812 +                    device->DevChannels[3] = LFE;
   1.813 +                    device->DevChannels[4] = BACK_LEFT;
   1.814 +                    device->DevChannels[5] = BACK_RIGHT;
   1.815 +                    device->DevChannels[6] = SIDE_LEFT;
   1.816 +                    device->DevChannels[7] = SIDE_RIGHT; break;
   1.817 +    }
   1.818 +}
   1.819 +
   1.820 +
   1.821 +const ALCchar *DevFmtTypeString(enum DevFmtType type)
   1.822 +{
   1.823 +    switch(type)
   1.824 +    {
   1.825 +    case DevFmtByte: return "Signed Byte";
   1.826 +    case DevFmtUByte: return "Unsigned Byte";
   1.827 +    case DevFmtShort: return "Signed Short";
   1.828 +    case DevFmtUShort: return "Unsigned Short";
   1.829 +    case DevFmtFloat: return "Float";
   1.830 +    }
   1.831 +    return "(unknown type)";
   1.832 +}
   1.833 +const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans)
   1.834 +{
   1.835 +    switch(chans)
   1.836 +    {
   1.837 +    case DevFmtMono: return "Mono";
   1.838 +    case DevFmtStereo: return "Stereo";
   1.839 +    case DevFmtQuad: return "Quadraphonic";
   1.840 +    case DevFmtX51: return "5.1 Surround";
   1.841 +    case DevFmtX51Side: return "5.1 Side";
   1.842 +    case DevFmtX61: return "6.1 Surround";
   1.843 +    case DevFmtX71: return "7.1 Surround";
   1.844 +    }
   1.845 +    return "(unknown channels)";
   1.846 +}
   1.847 +
   1.848 +ALuint BytesFromDevFmt(enum DevFmtType type)
   1.849 +{
   1.850 +    switch(type)
   1.851 +    {
   1.852 +    case DevFmtByte: return sizeof(ALbyte);
   1.853 +    case DevFmtUByte: return sizeof(ALubyte);
   1.854 +    case DevFmtShort: return sizeof(ALshort);
   1.855 +    case DevFmtUShort: return sizeof(ALushort);
   1.856 +    case DevFmtFloat: return sizeof(ALfloat);
   1.857 +    }
   1.858 +    return 0;
   1.859 +}
   1.860 +ALuint ChannelsFromDevFmt(enum DevFmtChannels chans)
   1.861 +{
   1.862 +    switch(chans)
   1.863 +    {
   1.864 +    case DevFmtMono: return 1;
   1.865 +    case DevFmtStereo: return 2;
   1.866 +    case DevFmtQuad: return 4;
   1.867 +    case DevFmtX51: return 6;
   1.868 +    case DevFmtX51Side: return 6;
   1.869 +    case DevFmtX61: return 7;
   1.870 +    case DevFmtX71: return 8;
   1.871 +    }
   1.872 +    return 0;
   1.873 +}
   1.874 +ALboolean DecomposeDevFormat(ALenum format, enum DevFmtChannels *chans,
   1.875 +                             enum DevFmtType *type)
   1.876 +{
   1.877 +    switch(format)
   1.878 +    {
   1.879 +        case AL_FORMAT_MONO8:
   1.880 +            *chans = DevFmtMono;
   1.881 +            *type  = DevFmtUByte;
   1.882 +            return AL_TRUE;
   1.883 +        case AL_FORMAT_MONO16:
   1.884 +            *chans = DevFmtMono;
   1.885 +            *type  = DevFmtShort;
   1.886 +            return AL_TRUE;
   1.887 +        case AL_FORMAT_MONO_FLOAT32:
   1.888 +            *chans = DevFmtMono;
   1.889 +            *type  = DevFmtFloat;
   1.890 +            return AL_TRUE;
   1.891 +        case AL_FORMAT_STEREO8:
   1.892 +            *chans = DevFmtStereo;
   1.893 +            *type  = DevFmtUByte;
   1.894 +            return AL_TRUE;
   1.895 +        case AL_FORMAT_STEREO16:
   1.896 +            *chans = DevFmtStereo;
   1.897 +            *type  = DevFmtShort;
   1.898 +            return AL_TRUE;
   1.899 +        case AL_FORMAT_STEREO_FLOAT32:
   1.900 +            *chans = DevFmtStereo;
   1.901 +            *type  = DevFmtFloat;
   1.902 +            return AL_TRUE;
   1.903 +        case AL_FORMAT_QUAD8:
   1.904 +            *chans = DevFmtQuad;
   1.905 +            *type  = DevFmtUByte;
   1.906 +            return AL_TRUE;
   1.907 +        case AL_FORMAT_QUAD16:
   1.908 +            *chans = DevFmtQuad;
   1.909 +            *type  = DevFmtShort;
   1.910 +            return AL_TRUE;
   1.911 +        case AL_FORMAT_QUAD32:
   1.912 +            *chans = DevFmtQuad;
   1.913 +            *type  = DevFmtFloat;
   1.914 +            return AL_TRUE;
   1.915 +        case AL_FORMAT_51CHN8:
   1.916 +            *chans = DevFmtX51;
   1.917 +            *type  = DevFmtUByte;
   1.918 +            return AL_TRUE;
   1.919 +        case AL_FORMAT_51CHN16:
   1.920 +            *chans = DevFmtX51;
   1.921 +            *type  = DevFmtShort;
   1.922 +            return AL_TRUE;
   1.923 +        case AL_FORMAT_51CHN32:
   1.924 +            *chans = DevFmtX51;
   1.925 +            *type  = DevFmtFloat;
   1.926 +            return AL_TRUE;
   1.927 +        case AL_FORMAT_61CHN8:
   1.928 +            *chans = DevFmtX61;
   1.929 +            *type  = DevFmtUByte;
   1.930 +            return AL_TRUE;
   1.931 +        case AL_FORMAT_61CHN16:
   1.932 +            *chans = DevFmtX61;
   1.933 +            *type  = DevFmtShort;
   1.934 +            return AL_TRUE;
   1.935 +        case AL_FORMAT_61CHN32:
   1.936 +            *chans = DevFmtX61;
   1.937 +            *type  = DevFmtFloat;
   1.938 +            return AL_TRUE;
   1.939 +        case AL_FORMAT_71CHN8:
   1.940 +            *chans = DevFmtX71;
   1.941 +            *type  = DevFmtUByte;
   1.942 +            return AL_TRUE;
   1.943 +        case AL_FORMAT_71CHN16:
   1.944 +            *chans = DevFmtX71;
   1.945 +            *type  = DevFmtShort;
   1.946 +            return AL_TRUE;
   1.947 +        case AL_FORMAT_71CHN32:
   1.948 +            *chans = DevFmtX71;
   1.949 +            *type  = DevFmtFloat;
   1.950 +            return AL_TRUE;
   1.951 +    }
   1.952 +    return AL_FALSE;
   1.953 +}
   1.954 +
   1.955 +static ALCboolean IsValidALCType(ALCenum type)
   1.956 +{
   1.957 +    switch(type)
   1.958 +    {
   1.959 +        case ALC_BYTE:
   1.960 +        case ALC_UNSIGNED_BYTE:
   1.961 +        case ALC_SHORT:
   1.962 +        case ALC_UNSIGNED_SHORT:
   1.963 +        case ALC_INT:
   1.964 +        case ALC_UNSIGNED_INT:
   1.965 +        case ALC_FLOAT:
   1.966 +            return ALC_TRUE;
   1.967 +    }
   1.968 +    return ALC_FALSE;
   1.969 +}
   1.970 +
   1.971 +static ALCboolean IsValidALCChannels(ALCenum channels)
   1.972 +{
   1.973 +    switch(channels)
   1.974 +    {
   1.975 +        case ALC_MONO:
   1.976 +        case ALC_STEREO:
   1.977 +        case ALC_QUAD:
   1.978 +        case ALC_5POINT1:
   1.979 +        case ALC_6POINT1:
   1.980 +        case ALC_7POINT1:
   1.981 +            return ALC_TRUE;
   1.982 +    }
   1.983 +    return ALC_FALSE;
   1.984 +}
   1.985 +
   1.986 +
   1.987 +static void LockLists(void)
   1.988 +{
   1.989 +    EnterCriticalSection(&ListLock);
   1.990 +}
   1.991 +
   1.992 +static void UnlockLists(void)
   1.993 +{
   1.994 +    LeaveCriticalSection(&ListLock);
   1.995 +}
   1.996 +
   1.997 +/*
   1.998 +    IsDevice
   1.999 +
  1.1000 +    Check pDevice is a valid Device pointer
  1.1001 +*/
  1.1002 +static ALCboolean IsDevice(ALCdevice *pDevice)
  1.1003 +{
  1.1004 +    ALCdevice *pTempDevice;
  1.1005 +
  1.1006 +    pTempDevice = g_pDeviceList;
  1.1007 +    while(pTempDevice && pTempDevice != pDevice)
  1.1008 +        pTempDevice = pTempDevice->next;
  1.1009 +
  1.1010 +    return (pTempDevice ? ALC_TRUE : ALC_FALSE);
  1.1011 +}
  1.1012 +
  1.1013 +/*
  1.1014 +    IsContext
  1.1015 +
  1.1016 +    Check pContext is a valid Context pointer
  1.1017 +*/
  1.1018 +static ALCboolean IsContext(ALCcontext *pContext)
  1.1019 +{
  1.1020 +    ALCcontext *pTempContext;
  1.1021 +
  1.1022 +    pTempContext = g_pContextList;
  1.1023 +    while (pTempContext && pTempContext != pContext)
  1.1024 +        pTempContext = pTempContext->next;
  1.1025 +
  1.1026 +    return (pTempContext ? ALC_TRUE : ALC_FALSE);
  1.1027 +}
  1.1028 +
  1.1029 +
  1.1030 +/*
  1.1031 +    alcSetError
  1.1032 +
  1.1033 +    Store latest ALC Error
  1.1034 +*/
  1.1035 +ALCvoid alcSetError(ALCdevice *device, ALenum errorCode)
  1.1036 +{
  1.1037 +    LockLists();
  1.1038 +    if(IsDevice(device))
  1.1039 +        device->LastError = errorCode;
  1.1040 +    else
  1.1041 +        g_eLastNullDeviceError = errorCode;
  1.1042 +    UnlockLists();
  1.1043 +}
  1.1044 +
  1.1045 +
  1.1046 +/* UpdateDeviceParams:
  1.1047 + *
  1.1048 + * Updates device parameters according to the attribute list.
  1.1049 + */
  1.1050 +static ALCboolean UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
  1.1051 +{
  1.1052 +    ALuint i;
  1.1053 +
  1.1054 +    // Check for attributes
  1.1055 +    if(attrList && attrList[0])
  1.1056 +    {
  1.1057 +        ALCuint freq, numMono, numStereo, numSends;
  1.1058 +        enum DevFmtChannels schans;
  1.1059 +        enum DevFmtType stype;
  1.1060 +        ALuint attrIdx;
  1.1061 +
  1.1062 +        // If a context is already running on the device, stop playback so the
  1.1063 +        // device attributes can be updated
  1.1064 +        if((device->Flags&DEVICE_RUNNING))
  1.1065 +            ALCdevice_StopPlayback(device);
  1.1066 +        device->Flags &= ~DEVICE_RUNNING;
  1.1067 +
  1.1068 +        freq = device->Frequency;
  1.1069 +        schans = device->FmtChans;
  1.1070 +        stype = device->FmtType;
  1.1071 +        numMono = device->NumMonoSources;
  1.1072 +        numStereo = device->NumStereoSources;
  1.1073 +        numSends = device->NumAuxSends;
  1.1074 +
  1.1075 +        freq = GetConfigValueInt(NULL, "frequency", freq);
  1.1076 +        if(freq < 8000) freq = 8000;
  1.1077 +
  1.1078 +        attrIdx = 0;
  1.1079 +        while(attrList[attrIdx])
  1.1080 +        {
  1.1081 +            if(attrList[attrIdx] == ALC_FORMAT_CHANNELS_SOFT &&
  1.1082 +               device->IsLoopbackDevice)
  1.1083 +            {
  1.1084 +                ALCint val = attrList[attrIdx + 1];
  1.1085 +                if(!IsValidALCChannels(val) || !ChannelsFromDevFmt(val))
  1.1086 +                {
  1.1087 +                    alcSetError(device, ALC_INVALID_VALUE);
  1.1088 +                    return ALC_FALSE;
  1.1089 +                }
  1.1090 +                schans = val;
  1.1091 +            }
  1.1092 +
  1.1093 +            if(attrList[attrIdx] == ALC_FORMAT_TYPE_SOFT &&
  1.1094 +               device->IsLoopbackDevice)
  1.1095 +            {
  1.1096 +                ALCint val = attrList[attrIdx + 1];
  1.1097 +                if(!IsValidALCType(val) || !BytesFromDevFmt(val))
  1.1098 +                {
  1.1099 +                    alcSetError(device, ALC_INVALID_VALUE);
  1.1100 +                    return ALC_FALSE;
  1.1101 +                }
  1.1102 +                stype = val;
  1.1103 +            }
  1.1104 +
  1.1105 +            if(attrList[attrIdx] == ALC_FREQUENCY)
  1.1106 +            {
  1.1107 +                if(device->IsLoopbackDevice)
  1.1108 +                {
  1.1109 +                    freq = attrList[attrIdx + 1];
  1.1110 +                    if(freq < 8000)
  1.1111 +                    {
  1.1112 +                        alcSetError(device, ALC_INVALID_VALUE);
  1.1113 +                        return ALC_FALSE;
  1.1114 +                    }
  1.1115 +                }
  1.1116 +                else if(!ConfigValueExists(NULL, "frequency"))
  1.1117 +                {
  1.1118 +                    freq = attrList[attrIdx + 1];
  1.1119 +                    if(freq < 8000) freq = 8000;
  1.1120 +                    device->Flags |= DEVICE_FREQUENCY_REQUEST;
  1.1121 +                }
  1.1122 +            }
  1.1123 +
  1.1124 +            if(attrList[attrIdx] == ALC_STEREO_SOURCES)
  1.1125 +            {
  1.1126 +                numStereo = attrList[attrIdx + 1];
  1.1127 +                if(numStereo > device->MaxNoOfSources)
  1.1128 +                    numStereo = device->MaxNoOfSources;
  1.1129 +
  1.1130 +                numMono = device->MaxNoOfSources - numStereo;
  1.1131 +            }
  1.1132 +
  1.1133 +            if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS &&
  1.1134 +               !ConfigValueExists(NULL, "sends"))
  1.1135 +            {
  1.1136 +                numSends = attrList[attrIdx + 1];
  1.1137 +                if(numSends > MAX_SENDS)
  1.1138 +                    numSends = MAX_SENDS;
  1.1139 +            }
  1.1140 +
  1.1141 +            attrIdx += 2;
  1.1142 +        }
  1.1143 +
  1.1144 +        device->UpdateSize = (ALuint64)device->UpdateSize * freq /
  1.1145 +                             device->Frequency;
  1.1146 +
  1.1147 +        device->Frequency = freq;
  1.1148 +        device->FmtChans = schans;
  1.1149 +        device->FmtType = stype;
  1.1150 +        device->NumMonoSources = numMono;
  1.1151 +        device->NumStereoSources = numStereo;
  1.1152 +        device->NumAuxSends = numSends;
  1.1153 +    }
  1.1154 +
  1.1155 +    if((device->Flags&DEVICE_RUNNING))
  1.1156 +        return ALC_TRUE;
  1.1157 +
  1.1158 +    LockDevice(device);
  1.1159 +    TRACE("Format pre-setup: %s%s, %s, %uhz%s, %u update size x%d\n",
  1.1160 +          DevFmtChannelsString(device->FmtChans),
  1.1161 +          (device->Flags&DEVICE_CHANNELS_REQUEST)?" (requested)":"",
  1.1162 +          DevFmtTypeString(device->FmtType), device->Frequency,
  1.1163 +          (device->Flags&DEVICE_FREQUENCY_REQUEST)?" (requested)":"",
  1.1164 +          device->UpdateSize, device->NumUpdates);
  1.1165 +    if(ALCdevice_ResetPlayback(device) == ALC_FALSE)
  1.1166 +    {
  1.1167 +        UnlockDevice(device);
  1.1168 +        return ALC_FALSE;
  1.1169 +    }
  1.1170 +    device->Flags |= DEVICE_RUNNING;
  1.1171 +    TRACE("Format post-setup: %s%s, %s, %uhz%s, %u update size x%d\n",
  1.1172 +          DevFmtChannelsString(device->FmtChans),
  1.1173 +          (device->Flags&DEVICE_CHANNELS_REQUEST)?" (requested)":"",
  1.1174 +          DevFmtTypeString(device->FmtType), device->Frequency,
  1.1175 +          (device->Flags&DEVICE_FREQUENCY_REQUEST)?" (requested)":"",
  1.1176 +          device->UpdateSize, device->NumUpdates);
  1.1177 +
  1.1178 +    aluInitPanning(device);
  1.1179 +
  1.1180 +    for(i = 0;i < MAXCHANNELS;i++)
  1.1181 +    {
  1.1182 +        device->ClickRemoval[i] = 0.0f;
  1.1183 +        device->PendingClicks[i] = 0.0f;
  1.1184 +    }
  1.1185 +
  1.1186 +    if(!device->IsLoopbackDevice && GetConfigValueBool(NULL, "hrtf", AL_FALSE))
  1.1187 +        device->Flags |= DEVICE_USE_HRTF;
  1.1188 +    if((device->Flags&DEVICE_USE_HRTF) && !IsHrtfCompatible(device))
  1.1189 +        device->Flags &= ~DEVICE_USE_HRTF;
  1.1190 +    TRACE("HRTF %s\n", (device->Flags&DEVICE_USE_HRTF)?"enabled":"disabled");
  1.1191 +
  1.1192 +    if(!(device->Flags&DEVICE_USE_HRTF) && device->Bs2bLevel > 0 && device->Bs2bLevel <= 6)
  1.1193 +    {
  1.1194 +        if(!device->Bs2b)
  1.1195 +        {
  1.1196 +            device->Bs2b = calloc(1, sizeof(*device->Bs2b));
  1.1197 +            bs2b_clear(device->Bs2b);
  1.1198 +        }
  1.1199 +        bs2b_set_srate(device->Bs2b, device->Frequency);
  1.1200 +        bs2b_set_level(device->Bs2b, device->Bs2bLevel);
  1.1201 +        TRACE("BS2B level %d\n", device->Bs2bLevel);
  1.1202 +    }
  1.1203 +    else
  1.1204 +    {
  1.1205 +        free(device->Bs2b);
  1.1206 +        device->Bs2b = NULL;
  1.1207 +        TRACE("BS2B disabled\n");
  1.1208 +    }
  1.1209 +
  1.1210 +    device->Flags &= ~DEVICE_DUPLICATE_STEREO;
  1.1211 +    switch(device->FmtChans)
  1.1212 +    {
  1.1213 +        case DevFmtMono:
  1.1214 +        case DevFmtStereo:
  1.1215 +            break;
  1.1216 +        case DevFmtQuad:
  1.1217 +        case DevFmtX51:
  1.1218 +        case DevFmtX51Side:
  1.1219 +        case DevFmtX61:
  1.1220 +        case DevFmtX71:
  1.1221 +            if(GetConfigValueBool(NULL, "stereodup", AL_TRUE))
  1.1222 +                device->Flags |= DEVICE_DUPLICATE_STEREO;
  1.1223 +            break;
  1.1224 +    }
  1.1225 +    TRACE("Stereo duplication %s\n", (device->Flags&DEVICE_DUPLICATE_STEREO)?"enabled":"disabled");
  1.1226 +
  1.1227 +    for(i = 0;i < device->NumContexts;i++)
  1.1228 +    {
  1.1229 +        ALCcontext *context = device->Contexts[i];
  1.1230 +        ALsizei pos;
  1.1231 +
  1.1232 +        context->UpdateSources = AL_FALSE;
  1.1233 +        for(pos = 0;pos < context->EffectSlotMap.size;pos++)
  1.1234 +        {
  1.1235 +            ALeffectslot *slot = context->EffectSlotMap.array[pos].value;
  1.1236 +
  1.1237 +            if(ALEffect_DeviceUpdate(slot->EffectState, device) == AL_FALSE)
  1.1238 +            {
  1.1239 +                UnlockDevice(device);
  1.1240 +                ALCdevice_StopPlayback(device);
  1.1241 +                device->Flags &= ~DEVICE_RUNNING;
  1.1242 +                return ALC_FALSE;
  1.1243 +            }
  1.1244 +            slot->NeedsUpdate = AL_FALSE;
  1.1245 +            ALEffect_Update(slot->EffectState, context, slot);
  1.1246 +        }
  1.1247 +
  1.1248 +        for(pos = 0;pos < context->SourceMap.size;pos++)
  1.1249 +        {
  1.1250 +            ALsource *source = context->SourceMap.array[pos].value;
  1.1251 +            ALuint s = device->NumAuxSends;
  1.1252 +            while(s < MAX_SENDS)
  1.1253 +            {
  1.1254 +                if(source->Send[s].Slot)
  1.1255 +                    source->Send[s].Slot->refcount--;
  1.1256 +                source->Send[s].Slot = NULL;
  1.1257 +                source->Send[s].WetFilter.type = 0;
  1.1258 +                source->Send[s].WetFilter.filter = 0;
  1.1259 +                s++;
  1.1260 +            }
  1.1261 +            source->NeedsUpdate = AL_FALSE;
  1.1262 +            ALsource_Update(source, context);
  1.1263 +        }
  1.1264 +    }
  1.1265 +    UnlockDevice(device);
  1.1266 +
  1.1267 +    return ALC_TRUE;
  1.1268 +}
  1.1269 +
  1.1270 +
  1.1271 +ALCvoid LockDevice(ALCdevice *device)
  1.1272 +{
  1.1273 +    EnterCriticalSection(&device->Mutex);
  1.1274 +}
  1.1275 +
  1.1276 +ALCvoid UnlockDevice(ALCdevice *device)
  1.1277 +{
  1.1278 +    LeaveCriticalSection(&device->Mutex);
  1.1279 +}
  1.1280 +
  1.1281 +/*
  1.1282 +    LockContext
  1.1283 +
  1.1284 +    Thread-safe entry
  1.1285 +*/
  1.1286 +ALCvoid LockContext(ALCcontext *context)
  1.1287 +{
  1.1288 +    EnterCriticalSection(&context->Device->Mutex);
  1.1289 +}
  1.1290 +
  1.1291 +
  1.1292 +/*
  1.1293 +    UnlockContext
  1.1294 +
  1.1295 +    Thread-safe exit
  1.1296 +*/
  1.1297 +ALCvoid UnlockContext(ALCcontext *context)
  1.1298 +{
  1.1299 +    LeaveCriticalSection(&context->Device->Mutex);
  1.1300 +}
  1.1301 +
  1.1302 +
  1.1303 +/*
  1.1304 +    GetLockedContext
  1.1305 +
  1.1306 +    Returns the currently active Context, in a locked state
  1.1307 +*/
  1.1308 +ALCcontext *GetLockedContext(void)
  1.1309 +{
  1.1310 +    ALCcontext *pContext = NULL;
  1.1311 +
  1.1312 +    LockLists();
  1.1313 +
  1.1314 +    pContext = tls_get(LocalContext);
  1.1315 +    if(pContext && !IsContext(pContext))
  1.1316 +    {
  1.1317 +        tls_set(LocalContext, NULL);
  1.1318 +        pContext = NULL;
  1.1319 +    }
  1.1320 +    if(!pContext)
  1.1321 +        pContext = GlobalContext;
  1.1322 +    if(pContext)
  1.1323 +        LockContext(pContext);
  1.1324 +
  1.1325 +    UnlockLists();
  1.1326 +
  1.1327 +    return pContext;
  1.1328 +}
  1.1329 +
  1.1330 +
  1.1331 +/*
  1.1332 +    InitContext
  1.1333 +
  1.1334 +    Initialize Context variables
  1.1335 +*/
  1.1336 +static ALvoid InitContext(ALCcontext *pContext)
  1.1337 +{
  1.1338 +    //Initialise listener
  1.1339 +    pContext->Listener.Gain = 1.0f;
  1.1340 +    pContext->Listener.MetersPerUnit = 1.0f;
  1.1341 +    pContext->Listener.Position[0] = 0.0f;
  1.1342 +    pContext->Listener.Position[1] = 0.0f;
  1.1343 +    pContext->Listener.Position[2] = 0.0f;
  1.1344 +    pContext->Listener.Velocity[0] = 0.0f;
  1.1345 +    pContext->Listener.Velocity[1] = 0.0f;
  1.1346 +    pContext->Listener.Velocity[2] = 0.0f;
  1.1347 +    pContext->Listener.Forward[0] = 0.0f;
  1.1348 +    pContext->Listener.Forward[1] = 0.0f;
  1.1349 +    pContext->Listener.Forward[2] = -1.0f;
  1.1350 +    pContext->Listener.Up[0] = 0.0f;
  1.1351 +    pContext->Listener.Up[1] = 1.0f;
  1.1352 +    pContext->Listener.Up[2] = 0.0f;
  1.1353 +
  1.1354 +    //Validate pContext
  1.1355 +    pContext->LastError = AL_NO_ERROR;
  1.1356 +    pContext->UpdateSources = AL_FALSE;
  1.1357 +    pContext->ActiveSourceCount = 0;
  1.1358 +    InitUIntMap(&pContext->SourceMap);
  1.1359 +    InitUIntMap(&pContext->EffectSlotMap);
  1.1360 +
  1.1361 +    //Set globals
  1.1362 +    pContext->DistanceModel = AL_INVERSE_DISTANCE_CLAMPED;
  1.1363 +    pContext->SourceDistanceModel = AL_FALSE;
  1.1364 +    pContext->DopplerFactor = 1.0f;
  1.1365 +    pContext->DopplerVelocity = 1.0f;
  1.1366 +    pContext->flSpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
  1.1367 +    pContext->DeferUpdates = AL_FALSE;
  1.1368 +
  1.1369 +    pContext->ExtensionList = alExtList;
  1.1370 +}
  1.1371 +
  1.1372 +
  1.1373 +/*
  1.1374 +    FreeContext
  1.1375 +
  1.1376 +    Clean up Context, destroy any remaining Sources
  1.1377 +*/
  1.1378 +static ALCvoid FreeContext(ALCcontext *context)
  1.1379 +{
  1.1380 +    //Invalidate context
  1.1381 +    memset(context, 0, sizeof(ALCcontext));
  1.1382 +    free(context);
  1.1383 +}
  1.1384 +
  1.1385 +///////////////////////////////////////////////////////
  1.1386 +
  1.1387 +
  1.1388 +///////////////////////////////////////////////////////
  1.1389 +// ALC Functions calls
  1.1390 +
  1.1391 +
  1.1392 +// This should probably move to another c file but for now ...
  1.1393 +ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei SampleSize)
  1.1394 +{
  1.1395 +    ALCdevice *device = NULL;
  1.1396 +
  1.1397 +    DO_INITCONFIG();
  1.1398 +
  1.1399 +    if(!CaptureBackend.name)
  1.1400 +    {
  1.1401 +        alcSetError(NULL, ALC_INVALID_VALUE);
  1.1402 +        return NULL;
  1.1403 +    }
  1.1404 +
  1.1405 +    if(SampleSize <= 0)
  1.1406 +    {
  1.1407 +        alcSetError(NULL, ALC_INVALID_VALUE);
  1.1408 +        return NULL;
  1.1409 +    }
  1.1410 +
  1.1411 +    if(deviceName && (!deviceName[0] || strcasecmp(deviceName, "openal soft") == 0 || strcasecmp(deviceName, "openal-soft") == 0))
  1.1412 +        deviceName = NULL;
  1.1413 +
  1.1414 +    device = calloc(1, sizeof(ALCdevice));
  1.1415 +    if(!device)
  1.1416 +    {
  1.1417 +        alcSetError(NULL, ALC_OUT_OF_MEMORY);
  1.1418 +        return NULL;
  1.1419 +    }
  1.1420 +
  1.1421 +    //Validate device
  1.1422 +    device->Funcs = &CaptureBackend.Funcs;
  1.1423 +    device->Connected = ALC_TRUE;
  1.1424 +    device->IsCaptureDevice = AL_TRUE;
  1.1425 +    device->IsLoopbackDevice = AL_FALSE;
  1.1426 +    InitializeCriticalSection(&device->Mutex);
  1.1427 +
  1.1428 +    device->szDeviceName = NULL;
  1.1429 +
  1.1430 +    device->Flags |= DEVICE_FREQUENCY_REQUEST;
  1.1431 +    device->Frequency = frequency;
  1.1432 +
  1.1433 +    device->Flags |= DEVICE_CHANNELS_REQUEST;
  1.1434 +    if(DecomposeDevFormat(format, &device->FmtChans, &device->FmtType) == AL_FALSE)
  1.1435 +    {
  1.1436 +        free(device);
  1.1437 +        alcSetError(NULL, ALC_INVALID_ENUM);
  1.1438 +        return NULL;
  1.1439 +    }
  1.1440 +
  1.1441 +    device->UpdateSize = SampleSize;
  1.1442 +    device->NumUpdates = 1;
  1.1443 +
  1.1444 +    LockLists();
  1.1445 +    if(ALCdevice_OpenCapture(device, deviceName))
  1.1446 +    {
  1.1447 +        device->next = g_pDeviceList;
  1.1448 +        g_pDeviceList = device;
  1.1449 +        g_ulDeviceCount++;
  1.1450 +    }
  1.1451 +    else
  1.1452 +    {
  1.1453 +        DeleteCriticalSection(&device->Mutex);
  1.1454 +        free(device);
  1.1455 +        device = NULL;
  1.1456 +        alcSetError(NULL, ALC_INVALID_VALUE);
  1.1457 +    }
  1.1458 +    UnlockLists();
  1.1459 +
  1.1460 +    return device;
  1.1461 +}
  1.1462 +
  1.1463 +ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *pDevice)
  1.1464 +{
  1.1465 +    ALCdevice **list;
  1.1466 +
  1.1467 +    LockLists();
  1.1468 +    list = &g_pDeviceList;
  1.1469 +    while(*list && *list != pDevice)
  1.1470 +        list = &(*list)->next;
  1.1471 +
  1.1472 +    if(!*list || !(*list)->IsCaptureDevice)
  1.1473 +    {
  1.1474 +        alcSetError(*list, ALC_INVALID_DEVICE);
  1.1475 +        UnlockLists();
  1.1476 +        return ALC_FALSE;
  1.1477 +    }
  1.1478 +
  1.1479 +    *list = (*list)->next;
  1.1480 +    g_ulDeviceCount--;
  1.1481 +
  1.1482 +    UnlockLists();
  1.1483 +
  1.1484 +    LockDevice(pDevice);
  1.1485 +    ALCdevice_CloseCapture(pDevice);
  1.1486 +    UnlockDevice(pDevice);
  1.1487 +
  1.1488 +    free(pDevice->szDeviceName);
  1.1489 +    pDevice->szDeviceName = NULL;
  1.1490 +
  1.1491 +    DeleteCriticalSection(&pDevice->Mutex);
  1.1492 +
  1.1493 +    free(pDevice);
  1.1494 +
  1.1495 +    return ALC_TRUE;
  1.1496 +}
  1.1497 +
  1.1498 +ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
  1.1499 +{
  1.1500 +    LockLists();
  1.1501 +    if(!IsDevice(device) || !device->IsCaptureDevice)
  1.1502 +    {
  1.1503 +        alcSetError(device, ALC_INVALID_DEVICE);
  1.1504 +        UnlockLists();
  1.1505 +        return;
  1.1506 +    }
  1.1507 +    LockDevice(device);
  1.1508 +    UnlockLists();
  1.1509 +    if(device->Connected)
  1.1510 +        ALCdevice_StartCapture(device);
  1.1511 +    UnlockDevice(device);
  1.1512 +}
  1.1513 +
  1.1514 +ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
  1.1515 +{
  1.1516 +    LockLists();
  1.1517 +    if(!IsDevice(device) || !device->IsCaptureDevice)
  1.1518 +    {
  1.1519 +        alcSetError(device, ALC_INVALID_DEVICE);
  1.1520 +        UnlockLists();
  1.1521 +        return;
  1.1522 +    }
  1.1523 +    LockDevice(device);
  1.1524 +    UnlockLists();
  1.1525 +    if(device->Connected)
  1.1526 +        ALCdevice_StopCapture(device);
  1.1527 +    UnlockDevice(device);
  1.1528 +}
  1.1529 +
  1.1530 +ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
  1.1531 +{
  1.1532 +    LockLists();
  1.1533 +    if(!IsDevice(device) || !device->IsCaptureDevice)
  1.1534 +    {
  1.1535 +        alcSetError(device, ALC_INVALID_DEVICE);
  1.1536 +        UnlockLists();
  1.1537 +        return;
  1.1538 +    }
  1.1539 +    LockDevice(device);
  1.1540 +    UnlockLists();
  1.1541 +    if(device->Connected)
  1.1542 +        ALCdevice_CaptureSamples(device, buffer, samples);
  1.1543 +    UnlockDevice(device);
  1.1544 +}
  1.1545 +
  1.1546 +/*
  1.1547 +    alcGetError
  1.1548 +
  1.1549 +    Return last ALC generated error code
  1.1550 +*/
  1.1551 +ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
  1.1552 +{
  1.1553 +    ALCenum errorCode;
  1.1554 +
  1.1555 +    LockLists();
  1.1556 +    if(IsDevice(device))
  1.1557 +    {
  1.1558 +        errorCode = device->LastError;
  1.1559 +        device->LastError = ALC_NO_ERROR;
  1.1560 +    }
  1.1561 +    else
  1.1562 +    {
  1.1563 +        errorCode = g_eLastNullDeviceError;
  1.1564 +        g_eLastNullDeviceError = ALC_NO_ERROR;
  1.1565 +    }
  1.1566 +    UnlockLists();
  1.1567 +    return errorCode;
  1.1568 +}
  1.1569 +
  1.1570 +
  1.1571 +/*
  1.1572 +    alcSuspendContext
  1.1573 +
  1.1574 +    Not functional
  1.1575 +*/
  1.1576 +ALC_API ALCvoid ALC_APIENTRY alcSuspendContext(ALCcontext *Context)
  1.1577 +{
  1.1578 +    (void)Context;
  1.1579 +}
  1.1580 +
  1.1581 +
  1.1582 +/*
  1.1583 +    alcProcessContext
  1.1584 +
  1.1585 +    Not functional
  1.1586 +*/
  1.1587 +ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *Context)
  1.1588 +{
  1.1589 +    (void)Context;
  1.1590 +}
  1.1591 +
  1.1592 +
  1.1593 +/*
  1.1594 +    alcGetString
  1.1595 +
  1.1596 +    Returns information about the Device, and error strings
  1.1597 +*/
  1.1598 +ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *pDevice,ALCenum param)
  1.1599 +{
  1.1600 +    const ALCchar *value = NULL;
  1.1601 +
  1.1602 +    switch(param)
  1.1603 +    {
  1.1604 +    case ALC_NO_ERROR:
  1.1605 +        value = alcNoError;
  1.1606 +        break;
  1.1607 +
  1.1608 +    case ALC_INVALID_ENUM:
  1.1609 +        value = alcErrInvalidEnum;
  1.1610 +        break;
  1.1611 +
  1.1612 +    case ALC_INVALID_VALUE:
  1.1613 +        value = alcErrInvalidValue;
  1.1614 +        break;
  1.1615 +
  1.1616 +    case ALC_INVALID_DEVICE:
  1.1617 +        value = alcErrInvalidDevice;
  1.1618 +        break;
  1.1619 +
  1.1620 +    case ALC_INVALID_CONTEXT:
  1.1621 +        value = alcErrInvalidContext;
  1.1622 +        break;
  1.1623 +
  1.1624 +    case ALC_OUT_OF_MEMORY:
  1.1625 +        value = alcErrOutOfMemory;
  1.1626 +        break;
  1.1627 +
  1.1628 +    case ALC_DEVICE_SPECIFIER:
  1.1629 +        LockLists();
  1.1630 +        if(IsDevice(pDevice))
  1.1631 +            value = pDevice->szDeviceName;
  1.1632 +        else
  1.1633 +        {
  1.1634 +            ProbeDeviceList();
  1.1635 +            value = alcDeviceList;
  1.1636 +        }
  1.1637 +        UnlockLists();
  1.1638 +        break;
  1.1639 +
  1.1640 +    case ALC_ALL_DEVICES_SPECIFIER:
  1.1641 +        ProbeAllDeviceList();
  1.1642 +        value = alcAllDeviceList;
  1.1643 +        break;
  1.1644 +
  1.1645 +    case ALC_CAPTURE_DEVICE_SPECIFIER:
  1.1646 +        LockLists();
  1.1647 +        if(IsDevice(pDevice))
  1.1648 +            value = pDevice->szDeviceName;
  1.1649 +        else
  1.1650 +        {
  1.1651 +            ProbeCaptureDeviceList();
  1.1652 +            value = alcCaptureDeviceList;
  1.1653 +        }
  1.1654 +        UnlockLists();
  1.1655 +        break;
  1.1656 +
  1.1657 +    /* Default devices are always first in the list */
  1.1658 +    case ALC_DEFAULT_DEVICE_SPECIFIER:
  1.1659 +        if(!alcDeviceList)
  1.1660 +            ProbeDeviceList();
  1.1661 +
  1.1662 +        free(alcDefaultDeviceSpecifier);
  1.1663 +        alcDefaultDeviceSpecifier = strdup(alcDeviceList ? alcDeviceList : "");
  1.1664 +        if(!alcDefaultDeviceSpecifier)
  1.1665 +            alcSetError(pDevice, ALC_OUT_OF_MEMORY);
  1.1666 +        value = alcDefaultDeviceSpecifier;
  1.1667 +        break;
  1.1668 +
  1.1669 +    case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
  1.1670 +        if(!alcAllDeviceList)
  1.1671 +            ProbeAllDeviceList();
  1.1672 +
  1.1673 +        free(alcDefaultAllDeviceSpecifier);
  1.1674 +        alcDefaultAllDeviceSpecifier = strdup(alcAllDeviceList ?
  1.1675 +                                              alcAllDeviceList : "");
  1.1676 +        if(!alcDefaultAllDeviceSpecifier)
  1.1677 +            alcSetError(pDevice, ALC_OUT_OF_MEMORY);
  1.1678 +        value = alcDefaultAllDeviceSpecifier;
  1.1679 +        break;
  1.1680 +
  1.1681 +    case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
  1.1682 +        if(!alcCaptureDeviceList)
  1.1683 +            ProbeCaptureDeviceList();
  1.1684 +
  1.1685 +        free(alcCaptureDefaultDeviceSpecifier);
  1.1686 +        alcCaptureDefaultDeviceSpecifier = strdup(alcCaptureDeviceList ?
  1.1687 +                                                  alcCaptureDeviceList : "");
  1.1688 +        if(!alcCaptureDefaultDeviceSpecifier)
  1.1689 +            alcSetError(pDevice, ALC_OUT_OF_MEMORY);
  1.1690 +        value = alcCaptureDefaultDeviceSpecifier;
  1.1691 +        break;
  1.1692 +
  1.1693 +    case ALC_EXTENSIONS:
  1.1694 +        LockLists();
  1.1695 +        if(IsDevice(pDevice))
  1.1696 +            value = alcExtensionList;
  1.1697 +        else
  1.1698 +            value = alcNoDeviceExtList;
  1.1699 +        UnlockLists();
  1.1700 +        break;
  1.1701 +
  1.1702 +    default:
  1.1703 +        alcSetError(pDevice, ALC_INVALID_ENUM);
  1.1704 +        break;
  1.1705 +    }
  1.1706 +
  1.1707 +    return value;
  1.1708 +}
  1.1709 +
  1.1710 +
  1.1711 +/*
  1.1712 +    alcGetIntegerv
  1.1713 +
  1.1714 +    Returns information about the Device and the version of Open AL
  1.1715 +*/
  1.1716 +ALC_API ALCvoid ALC_APIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsizei size,ALCint *data)
  1.1717 +{
  1.1718 +    if(size == 0 || data == NULL)
  1.1719 +    {
  1.1720 +        alcSetError(device, ALC_INVALID_VALUE);
  1.1721 +        return;
  1.1722 +    }
  1.1723 +
  1.1724 +    LockLists();
  1.1725 +    if(!IsDevice(device))
  1.1726 +    {
  1.1727 +        switch(param)
  1.1728 +        {
  1.1729 +            case ALC_MAJOR_VERSION:
  1.1730 +                *data = alcMajorVersion;
  1.1731 +                break;
  1.1732 +            case ALC_MINOR_VERSION:
  1.1733 +                *data = alcMinorVersion;
  1.1734 +                break;
  1.1735 +
  1.1736 +            case ALC_ATTRIBUTES_SIZE:
  1.1737 +            case ALC_ALL_ATTRIBUTES:
  1.1738 +            case ALC_FREQUENCY:
  1.1739 +            case ALC_REFRESH:
  1.1740 +            case ALC_SYNC:
  1.1741 +            case ALC_MONO_SOURCES:
  1.1742 +            case ALC_STEREO_SOURCES:
  1.1743 +            case ALC_CAPTURE_SAMPLES:
  1.1744 +            case ALC_FORMAT_CHANNELS_SOFT:
  1.1745 +            case ALC_FORMAT_TYPE_SOFT:
  1.1746 +                alcSetError(NULL, ALC_INVALID_DEVICE);
  1.1747 +                break;
  1.1748 +
  1.1749 +            default:
  1.1750 +                alcSetError(NULL, ALC_INVALID_ENUM);
  1.1751 +                break;
  1.1752 +        }
  1.1753 +    }
  1.1754 +    else if(device->IsCaptureDevice)
  1.1755 +    {
  1.1756 +        switch(param)
  1.1757 +        {
  1.1758 +            case ALC_CAPTURE_SAMPLES:
  1.1759 +                LockDevice(device);
  1.1760 +                *data = ALCdevice_AvailableSamples(device);
  1.1761 +                UnlockDevice(device);
  1.1762 +                break;
  1.1763 +
  1.1764 +            case ALC_CONNECTED:
  1.1765 +                *data = device->Connected;
  1.1766 +                break;
  1.1767 +
  1.1768 +            default:
  1.1769 +                alcSetError(device, ALC_INVALID_ENUM);
  1.1770 +                break;
  1.1771 +        }
  1.1772 +    }
  1.1773 +    else /* render device */
  1.1774 +    {
  1.1775 +        switch(param)
  1.1776 +        {
  1.1777 +            case ALC_MAJOR_VERSION:
  1.1778 +                *data = alcMajorVersion;
  1.1779 +                break;
  1.1780 +
  1.1781 +            case ALC_MINOR_VERSION:
  1.1782 +                *data = alcMinorVersion;
  1.1783 +                break;
  1.1784 +
  1.1785 +            case ALC_EFX_MAJOR_VERSION:
  1.1786 +                *data = alcEFXMajorVersion;
  1.1787 +                break;
  1.1788 +
  1.1789 +            case ALC_EFX_MINOR_VERSION:
  1.1790 +                *data = alcEFXMinorVersion;
  1.1791 +                break;
  1.1792 +
  1.1793 +            case ALC_ATTRIBUTES_SIZE:
  1.1794 +                *data = 13;
  1.1795 +                break;
  1.1796 +
  1.1797 +            case ALC_ALL_ATTRIBUTES:
  1.1798 +                if(size < 13)
  1.1799 +                    alcSetError(device, ALC_INVALID_VALUE);
  1.1800 +                else
  1.1801 +                {
  1.1802 +                    int i = 0;
  1.1803 +
  1.1804 +                    data[i++] = ALC_FREQUENCY;
  1.1805 +                    data[i++] = device->Frequency;
  1.1806 +
  1.1807 +                    if(!device->IsLoopbackDevice)
  1.1808 +                    {
  1.1809 +                        data[i++] = ALC_REFRESH;
  1.1810 +                        data[i++] = device->Frequency / device->UpdateSize;
  1.1811 +
  1.1812 +                        data[i++] = ALC_SYNC;
  1.1813 +                        data[i++] = ALC_FALSE;
  1.1814 +                    }
  1.1815 +                    else
  1.1816 +                    {
  1.1817 +                        data[i++] = ALC_FORMAT_CHANNELS_SOFT;
  1.1818 +                        data[i++] = device->FmtChans;
  1.1819 +
  1.1820 +                        data[i++] = ALC_FORMAT_TYPE_SOFT;
  1.1821 +                        data[i++] = device->FmtType;
  1.1822 +                    }
  1.1823 +
  1.1824 +                    data[i++] = ALC_MONO_SOURCES;
  1.1825 +                    data[i++] = device->NumMonoSources;
  1.1826 +
  1.1827 +                    data[i++] = ALC_STEREO_SOURCES;
  1.1828 +                    data[i++] = device->NumStereoSources;
  1.1829 +
  1.1830 +                    data[i++] = ALC_MAX_AUXILIARY_SENDS;
  1.1831 +                    data[i++] = device->NumAuxSends;
  1.1832 +
  1.1833 +                    data[i++] = 0;
  1.1834 +                }
  1.1835 +                break;
  1.1836 +
  1.1837 +            case ALC_FREQUENCY:
  1.1838 +                *data = device->Frequency;
  1.1839 +                break;
  1.1840 +
  1.1841 +            case ALC_REFRESH:
  1.1842 +                if(device->IsLoopbackDevice)
  1.1843 +                    alcSetError(device, ALC_INVALID_DEVICE);
  1.1844 +                else
  1.1845 +                    *data = device->Frequency / device->UpdateSize;
  1.1846 +                break;
  1.1847 +
  1.1848 +            case ALC_SYNC:
  1.1849 +                if(device->IsLoopbackDevice)
  1.1850 +                    alcSetError(device, ALC_INVALID_DEVICE);
  1.1851 +                else
  1.1852 +                    *data = ALC_FALSE;
  1.1853 +                break;
  1.1854 +
  1.1855 +            case ALC_FORMAT_CHANNELS_SOFT:
  1.1856 +                if(!device->IsLoopbackDevice)
  1.1857 +                    alcSetError(device, ALC_INVALID_DEVICE);
  1.1858 +                else
  1.1859 +                    *data = device->FmtChans;
  1.1860 +                break;
  1.1861 +
  1.1862 +            case ALC_FORMAT_TYPE_SOFT:
  1.1863 +                if(!device->IsLoopbackDevice)
  1.1864 +                    alcSetError(device, ALC_INVALID_DEVICE);
  1.1865 +                else
  1.1866 +                    *data = device->FmtType;
  1.1867 +                break;
  1.1868 +
  1.1869 +            case ALC_MONO_SOURCES:
  1.1870 +                *data = device->NumMonoSources;
  1.1871 +                break;
  1.1872 +
  1.1873 +            case ALC_STEREO_SOURCES:
  1.1874 +                *data = device->NumStereoSources;
  1.1875 +                break;
  1.1876 +
  1.1877 +            case ALC_MAX_AUXILIARY_SENDS:
  1.1878 +                *data = device->NumAuxSends;
  1.1879 +                break;
  1.1880 +
  1.1881 +            case ALC_CONNECTED:
  1.1882 +                *data = device->Connected;
  1.1883 +                break;
  1.1884 +
  1.1885 +            default:
  1.1886 +                alcSetError(device, ALC_INVALID_ENUM);
  1.1887 +                break;
  1.1888 +        }
  1.1889 +    }
  1.1890 +    UnlockLists();
  1.1891 +}
  1.1892 +
  1.1893 +
  1.1894 +/*
  1.1895 +    alcIsExtensionPresent
  1.1896 +
  1.1897 +    Determines if there is support for a particular extension
  1.1898 +*/
  1.1899 +ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
  1.1900 +{
  1.1901 +    ALCboolean bResult = ALC_FALSE;
  1.1902 +    const char *ptr;
  1.1903 +    size_t len;
  1.1904 +
  1.1905 +    if(!extName)
  1.1906 +    {
  1.1907 +        alcSetError(device, ALC_INVALID_VALUE);
  1.1908 +        return ALC_FALSE;
  1.1909 +    }
  1.1910 +
  1.1911 +    len = strlen(extName);
  1.1912 +    LockLists();
  1.1913 +    ptr = (IsDevice(device) ? alcExtensionList : alcNoDeviceExtList);
  1.1914 +    UnlockLists();
  1.1915 +    while(ptr && *ptr)
  1.1916 +    {
  1.1917 +        if(strncasecmp(ptr, extName, len) == 0 &&
  1.1918 +           (ptr[len] == '\0' || isspace(ptr[len])))
  1.1919 +        {
  1.1920 +            bResult = ALC_TRUE;
  1.1921 +            break;
  1.1922 +        }
  1.1923 +        if((ptr=strchr(ptr, ' ')) != NULL)
  1.1924 +        {
  1.1925 +            do {
  1.1926 +                ++ptr;
  1.1927 +            } while(isspace(*ptr));
  1.1928 +        }
  1.1929 +    }
  1.1930 +
  1.1931 +    return bResult;
  1.1932 +}
  1.1933 +
  1.1934 +
  1.1935 +/*
  1.1936 +    alcGetProcAddress
  1.1937 +
  1.1938 +    Retrieves the function address for a particular extension function
  1.1939 +*/
  1.1940 +ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
  1.1941 +{
  1.1942 +    ALsizei i = 0;
  1.1943 +
  1.1944 +    if(!funcName)
  1.1945 +    {
  1.1946 +        alcSetError(device, ALC_INVALID_VALUE);
  1.1947 +        return NULL;
  1.1948 +    }
  1.1949 +
  1.1950 +    while(alcFunctions[i].funcName && strcmp(alcFunctions[i].funcName,funcName) != 0)
  1.1951 +        i++;
  1.1952 +    return alcFunctions[i].address;
  1.1953 +}
  1.1954 +
  1.1955 +
  1.1956 +/*
  1.1957 +    alcGetEnumValue
  1.1958 +
  1.1959 +    Get the value for a particular ALC Enumerated Value
  1.1960 +*/
  1.1961 +ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
  1.1962 +{
  1.1963 +    ALsizei i = 0;
  1.1964 +
  1.1965 +    if(!enumName)
  1.1966 +    {
  1.1967 +        alcSetError(device, ALC_INVALID_VALUE);
  1.1968 +        return (ALCenum)0;
  1.1969 +    }
  1.1970 +
  1.1971 +    while(enumeration[i].enumName && strcmp(enumeration[i].enumName,enumName) != 0)
  1.1972 +        i++;
  1.1973 +    return enumeration[i].value;
  1.1974 +}
  1.1975 +
  1.1976 +
  1.1977 +/*
  1.1978 +    alcCreateContext
  1.1979 +
  1.1980 +    Create and attach a Context to a particular Device.
  1.1981 +*/
  1.1982 +ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
  1.1983 +{
  1.1984 +    ALCcontext *ALContext;
  1.1985 +    void *temp;
  1.1986 +
  1.1987 +    LockLists();
  1.1988 +    if(!IsDevice(device) || device->IsCaptureDevice || !device->Connected)
  1.1989 +    {
  1.1990 +        alcSetError(device, ALC_INVALID_DEVICE);
  1.1991 +        UnlockLists();
  1.1992 +        return NULL;
  1.1993 +    }
  1.1994 +
  1.1995 +    // Reset Context Last Error code
  1.1996 +    device->LastError = ALC_NO_ERROR;
  1.1997 +
  1.1998 +    if(UpdateDeviceParams(device, attrList) == ALC_FALSE)
  1.1999 +    {
  1.2000 +        alcSetError(device, ALC_INVALID_DEVICE);
  1.2001 +        aluHandleDisconnect(device);
  1.2002 +        UnlockLists();
  1.2003 +        return NULL;
  1.2004 +    }
  1.2005 +
  1.2006 +    LockDevice(device);
  1.2007 +    ALContext = NULL;
  1.2008 +    temp = realloc(device->Contexts, (device->NumContexts+1) * sizeof(*device->Contexts));
  1.2009 +    if(temp)
  1.2010 +    {
  1.2011 +        device->Contexts = temp;
  1.2012 +
  1.2013 +        ALContext = calloc(1, sizeof(ALCcontext));
  1.2014 +        if(ALContext)
  1.2015 +        {
  1.2016 +            ALContext->MaxActiveSources = 256;
  1.2017 +            ALContext->ActiveSources = malloc(sizeof(ALContext->ActiveSources[0]) *
  1.2018 +                                              ALContext->MaxActiveSources);
  1.2019 +        }
  1.2020 +    }
  1.2021 +    if(!ALContext || !ALContext->ActiveSources)
  1.2022 +    {
  1.2023 +        free(ALContext);
  1.2024 +        alcSetError(device, ALC_OUT_OF_MEMORY);
  1.2025 +        UnlockDevice(device);
  1.2026 +        if(device->NumContexts == 0)
  1.2027 +        {
  1.2028 +            ALCdevice_StopPlayback(device);
  1.2029 +            device->Flags &= ~DEVICE_RUNNING;
  1.2030 +        }
  1.2031 +        UnlockLists();
  1.2032 +        return NULL;
  1.2033 +    }
  1.2034 +
  1.2035 +    device->Contexts[device->NumContexts++] = ALContext;
  1.2036 +    ALContext->Device = device;
  1.2037 +
  1.2038 +    InitContext(ALContext);
  1.2039 +    UnlockDevice(device);
  1.2040 +
  1.2041 +    ALContext->next = g_pContextList;
  1.2042 +    g_pContextList = ALContext;
  1.2043 +    g_ulContextCount++;
  1.2044 +
  1.2045 +    UnlockLists();
  1.2046 +
  1.2047 +    return ALContext;
  1.2048 +}
  1.2049 +
  1.2050 +
  1.2051 +/*
  1.2052 +    alcDestroyContext
  1.2053 +
  1.2054 +    Remove a Context
  1.2055 +*/
  1.2056 +ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
  1.2057 +{
  1.2058 +    ALCdevice *Device;
  1.2059 +    ALCcontext **list;
  1.2060 +    ALuint i;
  1.2061 +
  1.2062 +    LockLists();
  1.2063 +    list = &g_pContextList;
  1.2064 +    while(*list && *list != context)
  1.2065 +        list = &(*list)->next;
  1.2066 +
  1.2067 +    if(!*list)
  1.2068 +    {
  1.2069 +        alcSetError(NULL, ALC_INVALID_CONTEXT);
  1.2070 +        UnlockLists();
  1.2071 +        return;
  1.2072 +    }
  1.2073 +
  1.2074 +    *list = (*list)->next;
  1.2075 +    g_ulContextCount--;
  1.2076 +
  1.2077 +    if(context == tls_get(LocalContext))
  1.2078 +        tls_set(LocalContext, NULL);
  1.2079 +    if(context == GlobalContext)
  1.2080 +        GlobalContext = NULL;
  1.2081 +
  1.2082 +    Device = context->Device;
  1.2083 +    LockDevice(Device);
  1.2084 +    for(i = 0;i < Device->NumContexts;i++)
  1.2085 +    {
  1.2086 +        if(Device->Contexts[i] == context)
  1.2087 +        {
  1.2088 +            Device->Contexts[i] = Device->Contexts[Device->NumContexts-1];
  1.2089 +            Device->NumContexts--;
  1.2090 +            break;
  1.2091 +        }
  1.2092 +    }
  1.2093 +    UnlockDevice(Device);
  1.2094 +
  1.2095 +    if(Device->NumContexts == 0)
  1.2096 +    {
  1.2097 +        ALCdevice_StopPlayback(Device);
  1.2098 +        Device->Flags &= ~DEVICE_RUNNING;
  1.2099 +    }
  1.2100 +    UnlockLists();
  1.2101 +
  1.2102 +    if(context->SourceMap.size > 0)
  1.2103 +    {
  1.2104 +        ERR("alcDestroyContext(): deleting %d Source(s)\n", context->SourceMap.size);
  1.2105 +        ReleaseALSources(context);
  1.2106 +    }
  1.2107 +    ResetUIntMap(&context->SourceMap);
  1.2108 +
  1.2109 +    if(context->EffectSlotMap.size > 0)
  1.2110 +    {
  1.2111 +        ERR("alcDestroyContext(): deleting %d AuxiliaryEffectSlot(s)\n", context->EffectSlotMap.size);
  1.2112 +        ReleaseALAuxiliaryEffectSlots(context);
  1.2113 +    }
  1.2114 +    ResetUIntMap(&context->EffectSlotMap);
  1.2115 +
  1.2116 +    free(context->ActiveSources);
  1.2117 +    context->ActiveSources = NULL;
  1.2118 +    context->MaxActiveSources = 0;
  1.2119 +    context->ActiveSourceCount = 0;
  1.2120 +
  1.2121 +    FreeContext(context);
  1.2122 +}
  1.2123 +
  1.2124 +
  1.2125 +/*
  1.2126 +    alcGetCurrentContext
  1.2127 +
  1.2128 +    Returns the currently active Context
  1.2129 +*/
  1.2130 +ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(ALCvoid)
  1.2131 +{
  1.2132 +    ALCcontext *Context;
  1.2133 +
  1.2134 +    LockLists();
  1.2135 +    Context = tls_get(LocalContext);
  1.2136 +    if(Context && !IsContext(Context))
  1.2137 +    {
  1.2138 +        tls_set(LocalContext, NULL);
  1.2139 +        Context = NULL;
  1.2140 +    }
  1.2141 +    if(!Context)
  1.2142 +        Context = GlobalContext;
  1.2143 +    UnlockLists();
  1.2144 +
  1.2145 +    return Context;
  1.2146 +}
  1.2147 +
  1.2148 +/*
  1.2149 +    alcGetThreadContext
  1.2150 +
  1.2151 +    Returns the currently active thread-local Context
  1.2152 +*/
  1.2153 +ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
  1.2154 +{
  1.2155 +    ALCcontext *pContext = NULL;
  1.2156 +
  1.2157 +    LockLists();
  1.2158 +
  1.2159 +    pContext = tls_get(LocalContext);
  1.2160 +    if(pContext && !IsContext(pContext))
  1.2161 +    {
  1.2162 +        tls_set(LocalContext, NULL);
  1.2163 +        pContext = NULL;
  1.2164 +    }
  1.2165 +
  1.2166 +    UnlockLists();
  1.2167 +
  1.2168 +    return pContext;
  1.2169 +}
  1.2170 +
  1.2171 +
  1.2172 +/*
  1.2173 +    alcGetContextsDevice
  1.2174 +
  1.2175 +    Returns the Device that a particular Context is attached to
  1.2176 +*/
  1.2177 +ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *pContext)
  1.2178 +{
  1.2179 +    ALCdevice *pDevice = NULL;
  1.2180 +
  1.2181 +    LockLists();
  1.2182 +    if(IsContext(pContext))
  1.2183 +        pDevice = pContext->Device;
  1.2184 +    else
  1.2185 +        alcSetError(NULL, ALC_INVALID_CONTEXT);
  1.2186 +    UnlockLists();
  1.2187 +
  1.2188 +    return pDevice;
  1.2189 +}
  1.2190 +
  1.2191 +
  1.2192 +/*
  1.2193 +    alcMakeContextCurrent
  1.2194 +
  1.2195 +    Makes the given Context the active Context
  1.2196 +*/
  1.2197 +ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
  1.2198 +{
  1.2199 +    ALboolean bReturn = AL_TRUE;
  1.2200 +
  1.2201 +    LockLists();
  1.2202 +
  1.2203 +    // context must be a valid Context or NULL
  1.2204 +    if(context == NULL || IsContext(context))
  1.2205 +    {
  1.2206 +        GlobalContext = context;
  1.2207 +        tls_set(LocalContext, NULL);
  1.2208 +    }
  1.2209 +    else
  1.2210 +    {
  1.2211 +        alcSetError(NULL, ALC_INVALID_CONTEXT);
  1.2212 +        bReturn = AL_FALSE;
  1.2213 +    }
  1.2214 +
  1.2215 +    UnlockLists();
  1.2216 +
  1.2217 +    return bReturn;
  1.2218 +}
  1.2219 +
  1.2220 +/*
  1.2221 +    alcSetThreadContext
  1.2222 +
  1.2223 +    Makes the given Context the active Context for the current thread
  1.2224 +*/
  1.2225 +ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
  1.2226 +{
  1.2227 +    ALboolean bReturn = AL_TRUE;
  1.2228 +
  1.2229 +    LockLists();
  1.2230 +
  1.2231 +    // context must be a valid Context or NULL
  1.2232 +    if(context == NULL || IsContext(context))
  1.2233 +        tls_set(LocalContext, context);
  1.2234 +    else
  1.2235 +    {
  1.2236 +        alcSetError(NULL, ALC_INVALID_CONTEXT);
  1.2237 +        bReturn = AL_FALSE;
  1.2238 +    }
  1.2239 +
  1.2240 +    UnlockLists();
  1.2241 +
  1.2242 +    return bReturn;
  1.2243 +}
  1.2244 +
  1.2245 +
  1.2246 +static void GetFormatFromString(const char *str, enum DevFmtChannels *chans, enum DevFmtType *type)
  1.2247 +{
  1.2248 +    if(strcasecmp(str, "AL_FORMAT_MONO32") == 0)
  1.2249 +    {
  1.2250 +        *chans = DevFmtMono;
  1.2251 +        *type = DevFmtFloat;
  1.2252 +        return;
  1.2253 +    }
  1.2254 +    if(strcasecmp(str, "AL_FORMAT_STEREO32") == 0)
  1.2255 +    {
  1.2256 +        *chans = DevFmtStereo;
  1.2257 +        *type = DevFmtFloat;
  1.2258 +        return;
  1.2259 +    }
  1.2260 +    if(strcasecmp(str, "AL_FORMAT_QUAD32") == 0)
  1.2261 +    {
  1.2262 +        *chans = DevFmtQuad;
  1.2263 +        *type = DevFmtFloat;
  1.2264 +        return;
  1.2265 +    }
  1.2266 +    if(strcasecmp(str, "AL_FORMAT_51CHN32") == 0)
  1.2267 +    {
  1.2268 +        *chans = DevFmtX51;
  1.2269 +        *type = DevFmtFloat;
  1.2270 +        return;
  1.2271 +    }
  1.2272 +    if(strcasecmp(str, "AL_FORMAT_61CHN32") == 0)
  1.2273 +    {
  1.2274 +        *chans = DevFmtX61;
  1.2275 +        *type = DevFmtFloat;
  1.2276 +        return;
  1.2277 +    }
  1.2278 +    if(strcasecmp(str, "AL_FORMAT_71CHN32") == 0)
  1.2279 +    {
  1.2280 +        *chans = DevFmtX71;
  1.2281 +        *type = DevFmtFloat;
  1.2282 +        return;
  1.2283 +    }
  1.2284 +
  1.2285 +    if(strcasecmp(str, "AL_FORMAT_MONO16") == 0)
  1.2286 +    {
  1.2287 +        *chans = DevFmtMono;
  1.2288 +        *type = DevFmtShort;
  1.2289 +        return;
  1.2290 +    }
  1.2291 +    if(strcasecmp(str, "AL_FORMAT_STEREO16") == 0)
  1.2292 +    {
  1.2293 +        *chans = DevFmtStereo;
  1.2294 +        *type = DevFmtShort;
  1.2295 +        return;
  1.2296 +    }
  1.2297 +    if(strcasecmp(str, "AL_FORMAT_QUAD16") == 0)
  1.2298 +    {
  1.2299 +        *chans = DevFmtQuad;
  1.2300 +        *type = DevFmtShort;
  1.2301 +        return;
  1.2302 +    }
  1.2303 +    if(strcasecmp(str, "AL_FORMAT_51CHN16") == 0)
  1.2304 +    {
  1.2305 +        *chans = DevFmtX51;
  1.2306 +        *type = DevFmtShort;
  1.2307 +        return;
  1.2308 +    }
  1.2309 +    if(strcasecmp(str, "AL_FORMAT_61CHN16") == 0)
  1.2310 +    {
  1.2311 +        *chans = DevFmtX61;
  1.2312 +        *type = DevFmtShort;
  1.2313 +        return;
  1.2314 +    }
  1.2315 +    if(strcasecmp(str, "AL_FORMAT_71CHN16") == 0)
  1.2316 +    {
  1.2317 +        *chans = DevFmtX71;
  1.2318 +        *type = DevFmtShort;
  1.2319 +        return;
  1.2320 +    }
  1.2321 +
  1.2322 +    if(strcasecmp(str, "AL_FORMAT_MONO8") == 0)
  1.2323 +    {
  1.2324 +        *chans = DevFmtMono;
  1.2325 +        *type = DevFmtByte;
  1.2326 +        return;
  1.2327 +    }
  1.2328 +    if(strcasecmp(str, "AL_FORMAT_STEREO8") == 0)
  1.2329 +    {
  1.2330 +        *chans = DevFmtStereo;
  1.2331 +        *type = DevFmtByte;
  1.2332 +        return;
  1.2333 +    }
  1.2334 +    if(strcasecmp(str, "AL_FORMAT_QUAD8") == 0)
  1.2335 +    {
  1.2336 +        *chans = DevFmtQuad;
  1.2337 +        *type = DevFmtByte;
  1.2338 +        return;
  1.2339 +    }
  1.2340 +    if(strcasecmp(str, "AL_FORMAT_51CHN8") == 0)
  1.2341 +    {
  1.2342 +        *chans = DevFmtX51;
  1.2343 +        *type = DevFmtByte;
  1.2344 +        return;
  1.2345 +    }
  1.2346 +    if(strcasecmp(str, "AL_FORMAT_61CHN8") == 0)
  1.2347 +    {
  1.2348 +        *chans = DevFmtX61;
  1.2349 +        *type = DevFmtByte;
  1.2350 +        return;
  1.2351 +    }
  1.2352 +    if(strcasecmp(str, "AL_FORMAT_71CHN8") == 0)
  1.2353 +    {
  1.2354 +        *chans = DevFmtX71;
  1.2355 +        *type = DevFmtByte;
  1.2356 +        return;
  1.2357 +    }
  1.2358 +
  1.2359 +    ERR("Unknown format: \"%s\"\n", str);
  1.2360 +    *chans = DevFmtStereo;
  1.2361 +    *type = DevFmtShort;
  1.2362 +}
  1.2363 +
  1.2364 +/*
  1.2365 +    alcOpenDevice
  1.2366 +
  1.2367 +    Open the Device specified.
  1.2368 +*/
  1.2369 +ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
  1.2370 +{
  1.2371 +    const ALCchar *fmt;
  1.2372 +    ALCdevice *device;
  1.2373 +
  1.2374 +    DO_INITCONFIG();
  1.2375 +
  1.2376 +    if(!PlaybackBackend.name)
  1.2377 +    {
  1.2378 +        alcSetError(NULL, ALC_INVALID_VALUE);
  1.2379 +        return NULL;
  1.2380 +    }
  1.2381 +
  1.2382 +    if(deviceName && (!deviceName[0] || strcasecmp(deviceName, "openal soft") == 0 || strcasecmp(deviceName, "openal-soft") == 0))
  1.2383 +        deviceName = NULL;
  1.2384 +
  1.2385 +    device = calloc(1, sizeof(ALCdevice));
  1.2386 +    if(!device)
  1.2387 +    {
  1.2388 +        alcSetError(NULL, ALC_OUT_OF_MEMORY);
  1.2389 +        return NULL;
  1.2390 +    }
  1.2391 +
  1.2392 +    //Validate device
  1.2393 +    device->Funcs = &PlaybackBackend.Funcs;
  1.2394 +    device->Connected = ALC_TRUE;
  1.2395 +    device->IsCaptureDevice = AL_FALSE;
  1.2396 +    device->IsLoopbackDevice = AL_FALSE;
  1.2397 +    InitializeCriticalSection(&device->Mutex);
  1.2398 +    device->LastError = ALC_NO_ERROR;
  1.2399 +
  1.2400 +    device->Flags = 0;
  1.2401 +    device->Bs2b = NULL;
  1.2402 +    device->szDeviceName = NULL;
  1.2403 +
  1.2404 +    device->Contexts = NULL;
  1.2405 +    device->NumContexts = 0;
  1.2406 +
  1.2407 +    InitUIntMap(&device->BufferMap);
  1.2408 +    InitUIntMap(&device->EffectMap);
  1.2409 +    InitUIntMap(&device->FilterMap);
  1.2410 +
  1.2411 +    //Set output format
  1.2412 +    if(ConfigValueExists(NULL, "frequency"))
  1.2413 +        device->Flags |= DEVICE_FREQUENCY_REQUEST;
  1.2414 +    device->Frequency = GetConfigValueInt(NULL, "frequency", DEFAULT_OUTPUT_RATE);
  1.2415 +    if(device->Frequency < 8000)
  1.2416 +        device->Frequency = 8000;
  1.2417 +
  1.2418 +    if(ConfigValueExists(NULL, "format"))
  1.2419 +        device->Flags |= DEVICE_CHANNELS_REQUEST;
  1.2420 +    fmt = GetConfigValue(NULL, "format", "AL_FORMAT_STEREO16");
  1.2421 +    GetFormatFromString(fmt, &device->FmtChans, &device->FmtType);
  1.2422 +
  1.2423 +    device->NumUpdates = GetConfigValueInt(NULL, "periods", 4);
  1.2424 +    if(device->NumUpdates < 2)
  1.2425 +        device->NumUpdates = 4;
  1.2426 +
  1.2427 +    device->UpdateSize = GetConfigValueInt(NULL, "period_size", 1024);
  1.2428 +    if(device->UpdateSize <= 0)
  1.2429 +        device->UpdateSize = 1024;
  1.2430 +
  1.2431 +    device->MaxNoOfSources = GetConfigValueInt(NULL, "sources", 256);
  1.2432 +    if(device->MaxNoOfSources <= 0)
  1.2433 +        device->MaxNoOfSources = 256;
  1.2434 +
  1.2435 +    device->AuxiliaryEffectSlotMax = GetConfigValueInt(NULL, "slots", 4);
  1.2436 +    if(device->AuxiliaryEffectSlotMax <= 0)
  1.2437 +        device->AuxiliaryEffectSlotMax = 4;
  1.2438 +
  1.2439 +    device->NumStereoSources = 1;
  1.2440 +    device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;
  1.2441 +
  1.2442 +    device->NumAuxSends = GetConfigValueInt(NULL, "sends", MAX_SENDS);
  1.2443 +    if(device->NumAuxSends > MAX_SENDS)
  1.2444 +        device->NumAuxSends = MAX_SENDS;
  1.2445 +
  1.2446 +    device->Bs2bLevel = GetConfigValueInt(NULL, "cf_level", 0);
  1.2447 +
  1.2448 +    // Find a playback device to open
  1.2449 +    LockLists();
  1.2450 +    if(ALCdevice_OpenPlayback(device, deviceName))
  1.2451 +    {
  1.2452 +        device->next = g_pDeviceList;
  1.2453 +        g_pDeviceList = device;
  1.2454 +        g_ulDeviceCount++;
  1.2455 +    }
  1.2456 +    else
  1.2457 +    {
  1.2458 +        // No suitable output device found
  1.2459 +        DeleteCriticalSection(&device->Mutex);
  1.2460 +        free(device);
  1.2461 +        device = NULL;
  1.2462 +        alcSetError(NULL, ALC_INVALID_VALUE);
  1.2463 +    }
  1.2464 +    UnlockLists();
  1.2465 +
  1.2466 +    return device;
  1.2467 +}
  1.2468 +
  1.2469 +
  1.2470 +/*
  1.2471 +    alcCloseDevice
  1.2472 +
  1.2473 +    Close the specified Device
  1.2474 +*/
  1.2475 +ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *pDevice)
  1.2476 +{
  1.2477 +    ALCdevice **list;
  1.2478 +
  1.2479 +    LockLists();
  1.2480 +    list = &g_pDeviceList;
  1.2481 +    while(*list && *list != pDevice)
  1.2482 +        list = &(*list)->next;
  1.2483 +
  1.2484 +    if(!*list || (*list)->IsCaptureDevice)
  1.2485 +    {
  1.2486 +        alcSetError(*list, ALC_INVALID_DEVICE);
  1.2487 +        UnlockLists();
  1.2488 +        return ALC_FALSE;
  1.2489 +    }
  1.2490 +
  1.2491 +    *list = (*list)->next;
  1.2492 +    g_ulDeviceCount--;
  1.2493 +
  1.2494 +    UnlockLists();
  1.2495 +
  1.2496 +    if(pDevice->NumContexts > 0)
  1.2497 +    {
  1.2498 +        WARN("alcCloseDevice(): destroying %u Context(s)\n", pDevice->NumContexts);
  1.2499 +        while(pDevice->NumContexts > 0)
  1.2500 +            alcDestroyContext(pDevice->Contexts[0]);
  1.2501 +    }
  1.2502 +    ALCdevice_ClosePlayback(pDevice);
  1.2503 +
  1.2504 +    if(pDevice->BufferMap.size > 0)
  1.2505 +    {
  1.2506 +        WARN("alcCloseDevice(): deleting %d Buffer(s)\n", pDevice->BufferMap.size);
  1.2507 +        ReleaseALBuffers(pDevice);
  1.2508 +    }
  1.2509 +    ResetUIntMap(&pDevice->BufferMap);
  1.2510 +
  1.2511 +    if(pDevice->EffectMap.size > 0)
  1.2512 +    {
  1.2513 +        WARN("alcCloseDevice(): deleting %d Effect(s)\n", pDevice->EffectMap.size);
  1.2514 +        ReleaseALEffects(pDevice);
  1.2515 +    }
  1.2516 +    ResetUIntMap(&pDevice->EffectMap);
  1.2517 +
  1.2518 +    if(pDevice->FilterMap.size > 0)
  1.2519 +    {
  1.2520 +        WARN("alcCloseDevice(): deleting %d Filter(s)\n", pDevice->FilterMap.size);
  1.2521 +        ReleaseALFilters(pDevice);
  1.2522 +    }
  1.2523 +    ResetUIntMap(&pDevice->FilterMap);
  1.2524 +
  1.2525 +    free(pDevice->Bs2b);
  1.2526 +    pDevice->Bs2b = NULL;
  1.2527 +
  1.2528 +    free(pDevice->szDeviceName);
  1.2529 +    pDevice->szDeviceName = NULL;
  1.2530 +
  1.2531 +    free(pDevice->Contexts);
  1.2532 +    pDevice->Contexts = NULL;
  1.2533 +
  1.2534 +    DeleteCriticalSection(&pDevice->Mutex);
  1.2535 +
  1.2536 +    //Release device structure
  1.2537 +    memset(pDevice, 0, sizeof(ALCdevice));
  1.2538 +    free(pDevice);
  1.2539 +
  1.2540 +    return ALC_TRUE;
  1.2541 +}
  1.2542 +
  1.2543 +
  1.2544 +ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(void)
  1.2545 +{
  1.2546 +    ALCdevice *device;
  1.2547 +
  1.2548 +    DO_INITCONFIG();
  1.2549 +
  1.2550 +    device = calloc(1, sizeof(ALCdevice));
  1.2551 +    if(!device)
  1.2552 +    {
  1.2553 +        alcSetError(NULL, ALC_OUT_OF_MEMORY);
  1.2554 +        return NULL;
  1.2555 +    }
  1.2556 +
  1.2557 +    //Validate device
  1.2558 +    device->Funcs = &BackendLoopback.Funcs;
  1.2559 +    device->Connected = ALC_TRUE;
  1.2560 +    device->IsCaptureDevice = AL_FALSE;
  1.2561 +    device->IsLoopbackDevice = AL_TRUE;
  1.2562 +    InitializeCriticalSection(&device->Mutex);
  1.2563 +    device->LastError = ALC_NO_ERROR;
  1.2564 +
  1.2565 +    device->Flags = 0;
  1.2566 +    device->Bs2b = NULL;
  1.2567 +    device->szDeviceName = NULL;
  1.2568 +
  1.2569 +    device->Contexts = NULL;
  1.2570 +    device->NumContexts = 0;
  1.2571 +
  1.2572 +    InitUIntMap(&device->BufferMap);
  1.2573 +    InitUIntMap(&device->EffectMap);
  1.2574 +    InitUIntMap(&device->FilterMap);
  1.2575 +
  1.2576 +    //Set output format
  1.2577 +    device->Frequency = 44100;
  1.2578 +    device->FmtChans = DevFmtStereo;
  1.2579 +    device->FmtType = DevFmtShort;
  1.2580 +
  1.2581 +    device->NumUpdates = 0;
  1.2582 +    device->UpdateSize = 0;
  1.2583 +
  1.2584 +    device->MaxNoOfSources = GetConfigValueInt(NULL, "sources", 256);
  1.2585 +    if(device->MaxNoOfSources <= 0)
  1.2586 +        device->MaxNoOfSources = 256;
  1.2587 +
  1.2588 +    device->AuxiliaryEffectSlotMax = GetConfigValueInt(NULL, "slots", 4);
  1.2589 +    if(device->AuxiliaryEffectSlotMax <= 0)
  1.2590 +        device->AuxiliaryEffectSlotMax = 4;
  1.2591 +
  1.2592 +    device->NumStereoSources = 1;
  1.2593 +    device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;
  1.2594 +
  1.2595 +    device->NumAuxSends = GetConfigValueInt(NULL, "sends", MAX_SENDS);
  1.2596 +    if(device->NumAuxSends > MAX_SENDS)
  1.2597 +        device->NumAuxSends = MAX_SENDS;
  1.2598 +
  1.2599 +    device->Bs2bLevel = GetConfigValueInt(NULL, "cf_level", 0);
  1.2600 +
  1.2601 +    // Open the "backend"
  1.2602 +    LockLists();
  1.2603 +    ALCdevice_OpenPlayback(device, "Loopback");
  1.2604 +
  1.2605 +    device->next = g_pDeviceList;
  1.2606 +    g_pDeviceList = device;
  1.2607 +    g_ulDeviceCount++;
  1.2608 +    UnlockLists();
  1.2609 +
  1.2610 +    return device;
  1.2611 +}
  1.2612 +
  1.2613 +ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
  1.2614 +{
  1.2615 +    ALCboolean ret = ALC_FALSE;
  1.2616 +
  1.2617 +    LockLists();
  1.2618 +    if(!IsDevice(device) || !device->IsLoopbackDevice)
  1.2619 +        alcSetError(device, ALC_INVALID_DEVICE);
  1.2620 +    else if(freq <= 0)
  1.2621 +        alcSetError(device, ALC_INVALID_VALUE);
  1.2622 +    else if(!IsValidALCType(type) || !IsValidALCChannels(channels))
  1.2623 +        alcSetError(device, ALC_INVALID_ENUM);
  1.2624 +    else
  1.2625 +    {
  1.2626 +        if(BytesFromDevFmt(type) > 0 && ChannelsFromDevFmt(channels) > 0 &&
  1.2627 +           freq >= 8000)
  1.2628 +            ret = ALC_TRUE;
  1.2629 +    }
  1.2630 +    UnlockLists();
  1.2631 +
  1.2632 +    return ret;
  1.2633 +}
  1.2634 +
  1.2635 +ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
  1.2636 +{
  1.2637 +    LockLists();
  1.2638 +    if(!IsDevice(device) || !device->IsLoopbackDevice)
  1.2639 +        alcSetError(device, ALC_INVALID_DEVICE);
  1.2640 +    else if(samples < 0 || (samples > 0 && buffer == NULL))
  1.2641 +        alcSetError(device, ALC_INVALID_VALUE);
  1.2642 +    else
  1.2643 +        aluMixData(device, buffer, samples);
  1.2644 +    UnlockLists();
  1.2645 +}
  1.2646 +
  1.2647 +
  1.2648 +static void ReleaseALC(ALCboolean doclose)
  1.2649 +{
  1.2650 +    free(alcDeviceList); alcDeviceList = NULL;
  1.2651 +    alcDeviceListSize = 0;
  1.2652 +    free(alcAllDeviceList); alcAllDeviceList = NULL;
  1.2653 +    alcAllDeviceListSize = 0;
  1.2654 +    free(alcCaptureDeviceList); alcCaptureDeviceList = NULL;
  1.2655 +    alcCaptureDeviceListSize = 0;
  1.2656 +
  1.2657 +    free(alcDefaultDeviceSpecifier);
  1.2658 +    alcDefaultDeviceSpecifier = NULL;
  1.2659 +    free(alcDefaultAllDeviceSpecifier);
  1.2660 +    alcDefaultAllDeviceSpecifier = NULL;
  1.2661 +    free(alcCaptureDefaultDeviceSpecifier);
  1.2662 +    alcCaptureDefaultDeviceSpecifier = NULL;
  1.2663 +
  1.2664 +    if(doclose)
  1.2665 +    {
  1.2666 +        if(g_ulDeviceCount > 0)
  1.2667 +            WARN("ReleaseALC(): closing %u Device%s\n", g_ulDeviceCount, (g_ulDeviceCount>1)?"s":"");
  1.2668 +
  1.2669 +        while(g_pDeviceList)
  1.2670 +        {
  1.2671 +            if(g_pDeviceList->IsCaptureDevice)
  1.2672 +                alcCaptureCloseDevice(g_pDeviceList);
  1.2673 +            else
  1.2674 +                alcCloseDevice(g_pDeviceList);
  1.2675 +        }
  1.2676 +    }
  1.2677 +    else
  1.2678 +    {
  1.2679 +        if(g_ulDeviceCount > 0)
  1.2680 +            WARN("ReleaseALC(): %u Device%s not closed\n", g_ulDeviceCount, (g_ulDeviceCount>1)?"s":"");
  1.2681 +    }
  1.2682 +}
  1.2683 +
  1.2684 +///////////////////////////////////////////////////////