Imported Upstream version 1.2 45/82145/1 upstream upstream/1.2
authorSeungbae Shin <seungbae.shin@samsung.com>
Mon, 1 Aug 2016 05:46:25 +0000 (14:46 +0900)
committerSeungbae Shin <seungbae.shin@samsung.com>
Mon, 1 Aug 2016 06:37:07 +0000 (15:37 +0900)
Change-Id: I7e5768d03a50b2ba1274e90ea27d7bf271fcf71d

61 files changed:
.gitignore [new file with mode: 0644]
CMakeLists.txt [new file with mode: 0644]
COPYING [new file with mode: 0644]
XCompile.txt [new file with mode: 0644]
alure-static.pc.in [new file with mode: 0644]
alure.pc.in [new file with mode: 0644]
build/.empty [new file with mode: 0644]
cmake/CheckCCompilerFlag.cmake [new file with mode: 0644]
cmake/CheckFileOffsetBits.c [new file with mode: 0644]
cmake/CheckFileOffsetBits.cmake [new file with mode: 0644]
cmake/CheckSharedFunctionExists.cmake [new file with mode: 0644]
cmake/FindFLAC.cmake [new file with mode: 0644]
cmake/FindOggVorbis.cmake [new file with mode: 0644]
cmake/FindOpenAL.cmake [new file with mode: 0644]
cmake/FindSndFile.cmake [new file with mode: 0644]
config.h.in [new file with mode: 0644]
docs/html/files/alure-cpp.html [new file with mode: 0644]
docs/html/files/buffer-cpp.html [new file with mode: 0644]
docs/html/files/istream-cpp.html [new file with mode: 0644]
docs/html/files/stream-cpp.html [new file with mode: 0644]
docs/html/files/streamplay-cpp.html [new file with mode: 0644]
docs/html/index.html [new file with mode: 0644]
docs/html/index/Functions.html [new file with mode: 0644]
docs/html/index/General.html [new file with mode: 0644]
docs/html/javascript/main.js [new file with mode: 0644]
docs/html/javascript/searchdata.js [new file with mode: 0644]
docs/html/search/FunctionsA.html [new file with mode: 0644]
docs/html/search/GeneralA.html [new file with mode: 0644]
docs/html/search/GeneralF.html [new file with mode: 0644]
docs/html/search/GeneralM.html [new file with mode: 0644]
docs/html/search/GeneralS.html [new file with mode: 0644]
docs/html/search/NoResults.html [new file with mode: 0644]
docs/html/styles/1.css [new file with mode: 0644]
docs/html/styles/2.css [new file with mode: 0644]
docs/html/styles/main.css [new file with mode: 0644]
docs/naturaldocs/CustomStyle.css [new file with mode: 0644]
docs/naturaldocs/Languages.txt [new file with mode: 0644]
docs/naturaldocs/Menu.txt [new file with mode: 0644]
docs/naturaldocs/Topics.txt [new file with mode: 0644]
examples/alurecdplay.c [new file with mode: 0644]
examples/alureplay.c [new file with mode: 0644]
examples/alurestream.c [new file with mode: 0644]
include/AL/alure.h [new file with mode: 0644]
include/alext.h [new file with mode: 0644]
include/main.h [new file with mode: 0644]
libalure.map [new file with mode: 0644]
src/alure.cpp [new file with mode: 0644]
src/buffer.cpp [new file with mode: 0644]
src/codec_aiff.cpp [new file with mode: 0644]
src/codec_dumb.cpp [new file with mode: 0644]
src/codec_flac.cpp [new file with mode: 0644]
src/codec_fluidsynth.cpp [new file with mode: 0644]
src/codec_modplug.cpp [new file with mode: 0644]
src/codec_mpg123.cpp [new file with mode: 0644]
src/codec_sndfile.cpp [new file with mode: 0644]
src/codec_vorbisfile.cpp [new file with mode: 0644]
src/codec_wav.cpp [new file with mode: 0644]
src/istream.cpp [new file with mode: 0644]
src/stream.cpp [new file with mode: 0644]
src/streamdec.cpp [new file with mode: 0644]
src/streamplay.cpp [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..d90cf8f
--- /dev/null
@@ -0,0 +1,3 @@
+build
+*.kdev4
+docs/naturaldocs/Data
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644 (file)
index 0000000..b0e45eb
--- /dev/null
@@ -0,0 +1,573 @@
+# CMakeLists.txt for ALURE
+CMAKE_MINIMUM_REQUIRED(VERSION 2.4)
+
+IF(COMMAND CMAKE_POLICY)
+    CMAKE_POLICY(SET CMP0003 NEW)
+ENDIF(COMMAND CMAKE_POLICY)
+
+SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
+
+INCLUDE(CheckCCompilerFlag)
+INCLUDE(CheckCSourceCompiles)
+INCLUDE(CheckFunctionExists)
+INCLUDE(CheckIncludeFile)
+INCLUDE(CheckIncludeFiles)
+INCLUDE(CheckLibraryExists)
+INCLUDE(CheckSharedFunctionExists)
+INCLUDE(FindPkgConfig)
+INCLUDE(UsePkgConfig)
+INCLUDE(CheckFileOffsetBits)
+
+PROJECT(ALURE)
+
+IF(WIN32)
+    SET(LIBNAME ALURE32)
+ELSE(WIN32)
+    SET(LIBNAME alure)
+ENDIF(WIN32)
+
+SET(LIB_MAJOR_VERSION "1")
+SET(LIB_MINOR_VERSION "2")
+SET(LIB_VERSION "${LIB_MAJOR_VERSION}.${LIB_MINOR_VERSION}")
+
+
+INCLUDE_DIRECTORIES(include "${ALURE_BINARY_DIR}")
+
+
+OPTION(BUILD_SHARED "Build the shared version of the library" ON)
+OPTION(BUILD_STATIC "Build the static version of the library" ON)
+
+IF(NOT BUILD_SHARED AND NOT BUILD_STATIC)
+    MESSAGE(FATAL_ERROR "No libtype being built!")
+ENDIF(NOT BUILD_SHARED AND NOT BUILD_STATIC)
+
+IF(NOT CMAKE_BUILD_TYPE)
+    SET(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING
+        "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel."
+        FORCE)
+ENDIF(NOT CMAKE_BUILD_TYPE)
+IF(NOT DEFINED CMAKE_DEBUG_POSTFIX)
+    SET(CMAKE_DEBUG_POSTFIX "" CACHE STRING
+        "Library postfix for debug builds. Normally left blank."
+        FORCE)
+ENDIF(NOT DEFINED CMAKE_DEBUG_POSTFIX)
+
+
+CHECK_LIBRARY_EXISTS(stdc++ memset "" HAS_STDCXX)
+IF(HAS_STDCXX)
+    SET(EXTRA_LIBS stdc++ ${EXTRA_LIBS})
+ENDIF(HAS_STDCXX)
+
+CHECK_LIBRARY_EXISTS(m pow "" HAS_LIBM)
+IF(HAS_LIBM)
+    SET(EXTRA_LIBS m ${EXTRA_LIBS})
+ENDIF(HAS_LIBM)
+
+CHECK_FILE_OFFSET_BITS()
+IF(_FILE_OFFSET_BITS)
+    ADD_DEFINITIONS(-D_FILE_OFFSET_BITS=${_FILE_OFFSET_BITS})
+    SET(CMAKE_REQUIRED_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} -D_FILE_OFFSET_BITS=${_FILE_OFFSET_BITS})
+ENDIF(_FILE_OFFSET_BITS)
+
+CHECK_FUNCTION_EXISTS(fseeko HAVE_FSEEKO)
+IF(NOT HAVE_FSEEKO)
+    CHECK_FUNCTION_EXISTS(_fseeki64 HAVE__FSEEKI64)
+ENDIF(NOT HAVE_FSEEKO)
+
+SET(STATIC_CFLAGS "${STATIC_CFLAGS} -DALURE_STATIC_LIBRARY")
+
+IF(MSVC)
+    # ???
+ELSE(MSVC)
+    IF(NOT WIN32)
+        CHECK_C_SOURCE_COMPILES("int foo() __attribute__((constructor));
+                                 int main() {return 0;}" HAVE_GCC_CONSTRUCTOR)
+
+        # Force -fPIC for the static lib, because it causes problems when the
+        # static version is linked to a dynamic lib
+        SET(STATIC_CFLAGS "${STATIC_CFLAGS} -fPIC")
+    ENDIF(NOT WIN32)
+
+    CHECK_C_COMPILER_FLAG(-Wextra HAVE_WEXTRA)
+    IF(HAVE_WEXTRA)
+        ADD_DEFINITIONS(-Wextra)
+    ENDIF(HAVE_WEXTRA)
+    ADD_DEFINITIONS(-Wall)
+
+    CHECK_C_COMPILER_FLAG(-funswitch-loops HAVE_FUNSWITCH_LOOPS)
+    IF(HAVE_FUNSWITCH_LOOPS)
+        ADD_DEFINITIONS(-funswitch-loops)
+    ENDIF(HAVE_FUNSWITCH_LOOPS)
+ENDIF(MSVC)
+
+# Set visibility/export options if available
+SET(EXPORT_DECL "")
+IF(WIN32)
+    SET(EXPORT_DECL "__declspec(dllexport)")
+ELSE(WIN32)
+    CHECK_C_COMPILER_FLAG(-fvisibility=hidden HAVE_VISIBILITY_SWITCH)
+    CHECK_C_SOURCE_COMPILES("int foo() __attribute__((visibility(\"protected\")));
+                             int main() {return 0;}" HAVE_GCC_VISIBILITY)
+    IF(HAVE_VISIBILITY_SWITCH AND HAVE_GCC_VISIBILITY)
+        ADD_DEFINITIONS(-fvisibility=hidden)
+        SET(EXPORT_DECL "__attribute__((visibility(\"protected\")))")
+    ENDIF(HAVE_VISIBILITY_SWITCH AND HAVE_GCC_VISIBILITY)
+ENDIF(WIN32)
+
+
+CHECK_INCLUDE_FILE(windows.h HAVE_WINDOWS_H -D_WIN32_WINNT=0x0500)
+IF(HAVE_WINDOWS_H)
+    CHECK_INCLUDE_FILE(ddk/ntddcdrm.h HAVE_DDK_NTDDCDRM_H)
+ELSE(HAVE_WINDOWS_H)
+    CHECK_C_COMPILER_FLAG(-pthread HAVE_PTHREAD)
+    IF(HAVE_PTHREAD)
+        ADD_DEFINITIONS(-pthread)
+        SET(EXTRA_LIBS ${EXTRA_LIBS} -pthread)
+    ENDIF(HAVE_PTHREAD)
+
+    # We need pthreads outside of Windows
+    CHECK_INCLUDE_FILE(pthread.h HAVE_PTHREAD_H)
+    IF(NOT HAVE_PTHREAD_H)
+        MESSAGE(FATAL_ERROR "PThreads is required for non-Windows builds!")
+    ENDIF()
+    # Some systems need pthread_np.h to get recursive mutexes
+    CHECK_INCLUDE_FILES("pthread.h;pthread_np.h" HAVE_PTHREAD_NP_H)
+
+    # _GNU_SOURCE is needed on some systems for extra attributes, and
+    # _REENTRANT is needed for libc thread-safety
+    ADD_DEFINITIONS(-D_GNU_SOURCE=1)
+    CHECK_FUNCTION_EXISTS(pthread_create HAS_PTHREAD_CREATE)
+    IF(NOT HAS_PTHREAD_CREATE)
+        CHECK_SHARED_FUNCTION_EXISTS(pthread_create "pthread.h" pthread "" HAVE_LIBPTHREAD)
+        IF(NOT HAVE_LIBPTHREAD)
+            MESSAGE(FATAL_ERROR "pthread_create not found on non-Windows target!")
+        ENDIF(NOT HAVE_LIBPTHREAD)
+        SET(EXTRA_LIBS pthread ${EXTRA_LIBS})
+    ENDIF(NOT HAS_PTHREAD_CREATE)
+
+    CHECK_FUNCTION_EXISTS(nanosleep HAVE_NANOSLEEP)
+    IF(NOT HAVE_NANOSLEEP)
+        MESSAGE(FATAL_ERROR "No sleep function found!")
+    ENDIF(NOT HAVE_NANOSLEEP)
+ENDIF(HAVE_WINDOWS_H)
+
+CHECK_INCLUDE_FILE(sys/types.h HAVE_SYS_TYPES_H)
+CHECK_INCLUDE_FILE(sys/wait.h HAVE_SYS_WAIT_H)
+CHECK_INCLUDE_FILE(signal.h HAVE_SIGNAL_H)
+CHECK_INCLUDE_FILE(dlfcn.h HAVE_DLFCN_H)
+
+IF(HAVE_DLFCN_H)
+    CHECK_SHARED_FUNCTION_EXISTS(dlopen "dlfcn.h" dl "" HAVE_LIBDL)
+    IF(HAVE_LIBDL)
+        SET(EXTRA_LIBS dl ${EXTRA_LIBS})
+    ENDIF(HAVE_LIBDL)
+ENDIF(HAVE_DLFCN_H)
+
+OPTION(DYNLOAD    "Dynamically load support libs at run-time" ON)
+OPTION(SNDFILE    "SoundFile support (for various formats)" ON)
+OPTION(VORBIS     "VorbisFile support (for Ogg Vorbis)"  ON)
+OPTION(FLAC       "FLAC support (for FLAC and Ogg FLAC)" ON)
+OPTION(MPG123     "MPG123 support (for MP1/MP2/MP3)" ON)
+OPTION(DUMB       "DUMB support (for IT/XM/S3M/MOD)" ON)
+OPTION(MODPLUG    "ModPlug support (for IT/XM/S3M/MOD)" OFF)
+OPTION(FLUIDSYNTH "FluidSynth support (for MID)" ON)
+
+IF(WIN32)
+    ADD_DEFINITIONS(-D_WIN32)
+ELSE(WIN32)
+    IF(NOT HAVE_DLFCN_H OR NOT HAVE_LIBDL)
+        SET(DYNLOAD OFF)
+    ENDIF(NOT HAVE_DLFCN_H OR NOT HAVE_LIBDL)
+    PKG_CHECK_MODULES(OPENAL openal)
+ENDIF(WIN32)
+
+IF(NOT OPENAL_FOUND)
+    FIND_PACKAGE(OpenAL)
+    IF(NOT OPENAL_FOUND)
+        MESSAGE(FATAL_ERROR "OpenAL not found!\nPlease try setting the OPENALDIR environment variable and try again.")
+    ENDIF(NOT OPENAL_FOUND)
+
+    MESSAGE(STATUS "OpenAL include: ${OPENAL_INCLUDE_DIR}")
+    MESSAGE(STATUS "OpenAL lib: ${OPENAL_LIBRARY}")
+
+    INCLUDE_DIRECTORIES(${OPENAL_INCLUDE_DIR})
+    SET(OPENAL_LIBRARIES ${OPENAL_LIBRARY})
+ELSE(NOT OPENAL_FOUND)
+    INCLUDE_DIRECTORIES(${OPENAL_INCLUDE_DIRS})
+    LINK_DIRECTORIES(${OPENAL_LIBRARY_DIRS})
+ENDIF(NOT OPENAL_FOUND)
+
+# Base source files
+SET(ALURE_OBJS  src/alure.cpp
+                src/buffer.cpp
+                src/istream.cpp
+                src/stream.cpp
+                src/streamdec.cpp
+                src/streamplay.cpp
+                src/codec_wav.cpp
+                src/codec_aiff.cpp
+)
+
+# SndFile support
+IF(SNDFILE)
+    PKG_CHECK_MODULES(SNDFILE sndfile)
+    IF(SNDFILE_FOUND)
+        SET(HAS_SNDFILE 1)
+        LINK_DIRECTORIES(${SNDFILE_LIBRARY_DIRS})
+        SET_SOURCE_FILES_PROPERTIES(src/codec_sndfile.cpp PROPERTIES
+                                    COMPILE_FLAGS "${SNDFILE_CFLAGS}")
+    ELSE(SNDFILE_FOUND)
+        FIND_PACKAGE(SndFile)
+        IF(SNDFILE_FOUND)
+            SET(HAS_SNDFILE 1)
+            INCLUDE_DIRECTORIES(${SNDFILE_INCLUDE_DIRS})
+        ENDIF(SNDFILE_FOUND)
+    ENDIF(SNDFILE_FOUND)
+    IF(HAS_SNDFILE)
+        SET(ALURE_OBJS ${ALURE_OBJS} src/codec_sndfile.cpp)
+    ENDIF(HAS_SNDFILE)
+ELSE(SNDFILE)
+    SET(SNDFILE_LIBRARIES "")
+ENDIF(SNDFILE)
+
+# Vorbis support
+IF(VORBIS)
+    PKG_CHECK_MODULES(VORBISFILE vorbisfile)
+    IF(VORBISFILE_FOUND)
+        SET(HAS_VORBISFILE 1)
+        LINK_DIRECTORIES(${VORBISFILE_LIBRARY_DIRS})
+        SET_SOURCE_FILES_PROPERTIES(src/codec_vorbisfile.cpp PROPERTIES
+                                    COMPILE_FLAGS "${VORBISFILE_CFLAGS}")
+    ELSE(VORBISFILE_FOUND)
+        FIND_PACKAGE(OggVorbis)
+        IF(OGGVORBIS_FOUND)
+            SET(HAS_VORBISFILE 1)
+            INCLUDE_DIRECTORIES(${OGGVORBIS_INCLUDE_DIRS})
+            SET(VORBISFILE_LIBRARIES ${OGGVORBIS_LIBRARIES})
+        ENDIF(OGGVORBIS_FOUND)
+    ENDIF(VORBISFILE_FOUND)
+    IF(NOT HAS_VORBISFILE)
+        PKG_CHECK_MODULES(VORBISIDEC vorbisidec)
+        IF(NOT VORBISIDEC_FOUND)
+            CHECK_INCLUDE_FILE(tremor/ivorbisfile.h HAVE_TREMOR_IVORBISFILE_H)
+            IF(HAVE_TREMOR_IVORBISFILE_H)
+                CHECK_SHARED_FUNCTION_EXISTS(ov_open "tremor/ivorbisfile.h" vorbisidec "" HAVE_LIBVORBISIDEC)
+                IF(DYNLOAD OR HAVE_LIBVORBISIDEC)
+                    SET(HAS_VORBISFILE 1)
+                    IF(HAVE_LIBVORBISIDEC)
+                        SET(VORBISFILE_LIBRARIES "vorbisidec")
+                    ENDIF(HAVE_LIBVORBISIDEC)
+                    SET_SOURCE_FILES_PROPERTIES(src/codec_vorbisfile.cpp PROPERTIES
+                                                COMPILE_FLAGS "-DHAS_VORBISIDEC")
+                ENDIF(DYNLOAD OR HAVE_LIBVORBISIDEC)
+            ENDIF(HAVE_TREMOR_IVORBISFILE_H)
+        ELSE(NOT VORBISIDEC_FOUND)
+            SET(HAS_VORBISFILE 1)
+            LINK_DIRECTORIES(${VORBISIDEC_LIBRARY_DIRS})
+            SET_SOURCE_FILES_PROPERTIES(src/codec_vorbisfile.cpp PROPERTIES
+                                        COMPILE_FLAGS "${VORBISIDEC_CFLAGS} -DHAS_VORBISIDEC")
+        ENDIF(NOT VORBISIDEC_FOUND)
+    ENDIF(NOT HAS_VORBISFILE)
+    IF(HAS_VORBISFILE)
+        SET(ALURE_OBJS ${ALURE_OBJS} src/codec_vorbisfile.cpp)
+    ENDIF(HAS_VORBISFILE)
+ELSE(VORBIS)
+    SET(VORBISFILE_LIBRARIES "")
+ENDIF(VORBIS)
+
+# FLAC support
+IF(FLAC)
+    FIND_PACKAGE(FLAC)
+    IF(FLAC_FOUND)
+        INCLUDE_DIRECTORIES(${FLAC_INCLUDE_DIR})
+        SET(HAS_FLAC 1)
+    ENDIF(FLAC_FOUND)
+    IF(HAS_FLAC)
+        SET(ALURE_OBJS ${ALURE_OBJS} src/codec_flac.cpp)
+    ENDIF(HAS_FLAC)
+ELSE(FLAC)
+    SET(LIBFLAC_LIBRARIES "")
+ENDIF(FLAC)
+
+# MPG123 support
+IF(MPG123)
+    PKG_CHECK_MODULES(MPG123 libmpg123)
+    IF(NOT MPG123_FOUND)
+        CHECK_INCLUDE_FILE(mpg123.h HAVE_MPG123_H)
+        IF(HAVE_MPG123_H)
+            CHECK_SHARED_FUNCTION_EXISTS(mpg123_init "mpg123.h" mpg123 "" HAVE_LIBMPG123)
+            IF(DYNLOAD OR HAVE_LIBMPG123)
+                SET(HAS_MPG123 1)
+                IF(HAVE_LIBMPG123)
+                    SET(MPG123_LIBRARIES "mpg123")
+                ENDIF(HAVE_LIBMPG123)
+            ENDIF(DYNLOAD OR HAVE_LIBMPG123)
+        ENDIF(HAVE_MPG123_H)
+    ELSE(NOT MPG123_FOUND)
+        SET(HAS_MPG123 1)
+        LINK_DIRECTORIES(${MPG123_LIBRARY_DIRS})
+        SET_SOURCE_FILES_PROPERTIES(src/codec_mpg123.cpp PROPERTIES
+                                    COMPILE_FLAGS "${MPG123_CFLAGS}")
+    ENDIF(NOT MPG123_FOUND)
+    IF(HAS_MPG123)
+        SET(ALURE_OBJS ${ALURE_OBJS} src/codec_mpg123.cpp)
+    ENDIF(HAS_MPG123)
+ELSE(MPG123)
+    SET(MPG123_LIBRARIES "")
+ENDIF(MPG123)
+
+# DUMB support
+IF(DUMB)
+    CHECK_INCLUDE_FILE(dumb.h HAVE_DUMB_H)
+    IF(HAVE_DUMB_H)
+        IF(HAS_LIBM)
+            CHECK_LIBRARY_EXISTS("dumb;m" dumbfile_open_ex "" HAVE_LIBDUMB)
+        ELSE(HAS_LIBM)
+            CHECK_LIBRARY_EXISTS(dumb dumbfile_open_ex "" HAVE_LIBDUMB)
+        ENDIF(HAS_LIBM)
+        IF(DYNLOAD OR HAVE_LIBDUMB)
+            SET(HAS_DUMB 1)
+            IF(HAVE_LIBDUMB)
+                SET(DUMB_LIBRARIES dumb)
+            ENDIF(HAVE_LIBDUMB)
+        ENDIF(DYNLOAD OR HAVE_LIBDUMB)
+    ENDIF(HAVE_DUMB_H)
+    IF(HAS_DUMB)
+        SET(ALURE_OBJS ${ALURE_OBJS} src/codec_dumb.cpp)
+    ENDIF(HAS_DUMB)
+ELSE(DUMB)
+    SET(DUMB_LIBRARIES "")
+ENDIF(DUMB)
+
+# ModPlug support
+IF(MODPLUG)
+    CHECK_INCLUDE_FILE(libmodplug/modplug.h HAVE_LIBMODPLUG_MODPLUG_H)
+    IF(HAVE_LIBMODPLUG_MODPLUG_H)
+        CHECK_SHARED_FUNCTION_EXISTS(ModPlug_Load "libmodplug/modplug.h" modplug "" HAVE_LIBMODPLUG)
+        IF(DYNLOAD OR HAVE_LIBMODPLUG)
+            SET(HAS_MODPLUG 1)
+            IF(HAVE_LIBMODPLUG)
+                SET(MODPLUG_LIBRARIES "modplug")
+            ENDIF(HAVE_LIBMODPLUG)
+        ENDIF(DYNLOAD OR HAVE_LIBMODPLUG)
+    ENDIF(HAVE_LIBMODPLUG_MODPLUG_H)
+    IF(HAS_MODPLUG)
+        SET(ALURE_OBJS ${ALURE_OBJS} src/codec_modplug.cpp)
+    ENDIF(HAS_MODPLUG)
+ELSE(MODPLUG)
+    SET(MODPLUG_LIBRARIES "")
+ENDIF(MODPLUG)
+
+# FluidSynth support
+IF(FLUIDSYNTH)
+    PKG_CHECK_MODULES(FLUIDSYNTH fluidsynth>=1.1.1)
+    IF(NOT FLUIDSYNTH_FOUND)
+        CHECK_INCLUDE_FILE(fluidsynth.h HAVE_FLUIDSYNTH_H)
+        IF(HAVE_FLUIDSYNTH_H)
+            CHECK_SHARED_FUNCTION_EXISTS(new_fluid_synth "fluidsynth.h" fluidsynth "" HAVE_LIBFLUIDSYNTH)
+            IF(DYNLOAD OR HAVE_LIBFLUIDSYNTH)
+                SET(HAS_FLUIDSYNTH 1)
+                IF(HAVE_LIBFLUIDSYNTH)
+                    SET(FLUIDSYNTH_LIBRARIES "fluidsynth")
+                ENDIF(HAVE_LIBFLUIDSYNTH)
+            ENDIF(DYNLOAD OR HAVE_LIBFLUIDSYNTH)
+        ENDIF(HAVE_FLUIDSYNTH_H)
+    ELSE(NOT FLUIDSYNTH_FOUND)
+        SET(HAS_FLUIDSYNTH 1)
+        LINK_DIRECTORIES(${FLUIDSYNTH_LIBRARY_DIRS})
+        SET_SOURCE_FILES_PROPERTIES(src/codec_fluidsynth.cpp PROPERTIES
+                                    COMPILE_FLAGS "${FLUIDSYNTH_CFLAGS}")
+    ENDIF(NOT FLUIDSYNTH_FOUND)
+    IF(HAS_FLUIDSYNTH)
+        SET(ALURE_OBJS ${ALURE_OBJS} src/codec_fluidsynth.cpp)
+    ENDIF(HAS_FLUIDSYNTH)
+ELSE(FLUIDSYNTH)
+    SET(FLUIDSYNTH_LIBRARIES "")
+ENDIF(FLUIDSYNTH)
+
+
+IF(NOT DYNLOAD)
+    SET(EXTRA_LIBS ${SNDFILE_LIBRARIES} ${VORBISFILE_LIBRARIES} ${LIBFLAC_LIBRARIES} ${MPG123_LIBRARIES} ${DUMB_LIBRARIES} ${MODPLUG_LIBRARIES} ${FLUIDSYNTH_LIBRARIES} ${EXTRA_LIBS})
+ELSE(NOT DYNLOAD)
+    ADD_DEFINITIONS(-DDYNLOAD=1)
+ENDIF(NOT DYNLOAD)
+
+# For alure.pc.in
+SET(prefix ${CMAKE_INSTALL_PREFIX})
+SET(exec_prefix "\${prefix}")
+SET(libdir "\${exec_prefix}/lib${LIB_SUFFIX}")
+SET(bindir "\${exec_prefix}/bin")
+SET(includedir "\${prefix}/include")
+SET(PKG_CONFIG_REQUIRES openal)
+SET(PACKAGE_VERSION "${LIB_VERSION}")
+
+# End configuration
+CONFIGURE_FILE(
+    "${ALURE_SOURCE_DIR}/config.h.in"
+    "${ALURE_BINARY_DIR}/config.h")
+IF(BUILD_SHARED)
+    CONFIGURE_FILE(
+        "${ALURE_SOURCE_DIR}/alure.pc.in"
+        "${ALURE_BINARY_DIR}/alure.pc"
+        @ONLY)
+ENDIF(BUILD_SHARED)
+IF(BUILD_STATIC)
+    CONFIGURE_FILE(
+        "${ALURE_SOURCE_DIR}/alure-static.pc.in"
+        "${ALURE_BINARY_DIR}/alure-static.pc"
+        @ONLY)
+ENDIF(BUILD_STATIC)
+
+ADD_DEFINITIONS(-DHAVE_CONFIG_H)
+
+
+IF(BUILD_SHARED)
+    #build a shared library
+    ADD_LIBRARY(${LIBNAME} SHARED ${ALURE_OBJS})
+    SET_TARGET_PROPERTIES(${LIBNAME} PROPERTIES DEFINE_SYMBOL ALURE_BUILD_LIBRARY
+                                                VERSION ${LIB_VERSION}.0
+                                                SOVERSION ${LIB_MAJOR_VERSION})
+    IF(WIN32)
+        SET_TARGET_PROPERTIES(${LIBNAME} PROPERTIES PREFIX "")
+    ELSEIF(NOT APPLE)
+        SET_TARGET_PROPERTIES(${LIBNAME} PROPERTIES LINK_FLAGS "-Wl,--version-script=${ALURE_SOURCE_DIR}/libalure.map")
+    ENDIF(WIN32)
+    TARGET_LINK_LIBRARIES(${LIBNAME} ${OPENAL_LIBRARIES} ${EXTRA_LIBS})
+
+    INSTALL(TARGETS ${LIBNAME}
+            RUNTIME DESTINATION bin
+            LIBRARY DESTINATION lib${LIB_SUFFIX}
+            ARCHIVE DESTINATION lib${LIB_SUFFIX}
+)
+ENDIF(BUILD_SHARED)
+IF(BUILD_STATIC)
+    #build a static library
+    ADD_LIBRARY(${LIBNAME}-static STATIC ${ALURE_OBJS})
+    SET_TARGET_PROPERTIES(${LIBNAME}-static PROPERTIES DEFINE_SYMBOL ALURE_BUILD_LIBRARY
+                                                       COMPILE_FLAGS ${STATIC_CFLAGS}
+                                                       VERSION ${LIB_VERSION}.0)
+    INSTALL(TARGETS ${LIBNAME}-static
+            RUNTIME DESTINATION bin
+            LIBRARY DESTINATION lib${LIB_SUFFIX}
+            ARCHIVE DESTINATION lib${LIB_SUFFIX}
+)
+ENDIF(BUILD_STATIC)
+
+
+OPTION(BUILD_EXAMPLES   "Build example programs"   ON)
+OPTION(INSTALL_EXAMPLES "Install example programs" ON)
+
+IF(BUILD_EXAMPLES)
+    IF(HAVE_DDK_NTDDCDRM_H)
+        SET_SOURCE_FILES_PROPERTIES(examples/alurecdplay.c PROPERTIES
+                                    COMPILE_FLAGS "-DHAVE_DDK_NTDDCDRM_H")
+    ENDIF(HAVE_DDK_NTDDCDRM_H)
+    ADD_EXECUTABLE(alureplay examples/alureplay.c)
+    ADD_EXECUTABLE(alurecdplay examples/alurecdplay.c)
+    ADD_EXECUTABLE(alurestream examples/alurestream.c)
+    IF(BUILD_SHARED)
+        TARGET_LINK_LIBRARIES(alureplay ${LIBNAME} ${OPENAL_LIBRARIES} ${EXTRA_LIBS})
+        TARGET_LINK_LIBRARIES(alurecdplay ${LIBNAME} ${OPENAL_LIBRARIES} ${EXTRA_LIBS})
+        TARGET_LINK_LIBRARIES(alurestream ${LIBNAME} ${OPENAL_LIBRARIES} ${EXTRA_LIBS})
+    ELSE(BUILD_SHARED)
+        SET_TARGET_PROPERTIES(alureplay PROPERTIES COMPILE_FLAGS -DALURE_STATIC_LIBRARY)
+        SET_TARGET_PROPERTIES(alurecdplay PROPERTIES COMPILE_FLAGS -DALURE_STATIC_LIBRARY)
+        SET_TARGET_PROPERTIES(alurestream PROPERTIES COMPILE_FLAGS -DALURE_STATIC_LIBRARY)
+        TARGET_LINK_LIBRARIES(alureplay ${LIBNAME}-static ${OPENAL_LIBRARIES} ${EXTRA_LIBS})
+        TARGET_LINK_LIBRARIES(alurecdplay ${LIBNAME}-static ${OPENAL_LIBRARIES} ${EXTRA_LIBS})
+        TARGET_LINK_LIBRARIES(alurestream ${LIBNAME}-static ${OPENAL_LIBRARIES} ${EXTRA_LIBS})
+    ENDIF(BUILD_SHARED)
+ENDIF(BUILD_EXAMPLES)
+
+
+FIND_PROGRAM(NATDOCS_BIN NaturalDocs)
+IF(NATDOCS_BIN)
+    ADD_CUSTOM_TARGET(docs
+                      "${NATDOCS_BIN}" -i "${ALURE_SOURCE_DIR}/src" -o HTML "${ALURE_SOURCE_DIR}/docs/html" -p "${ALURE_SOURCE_DIR}/docs/naturaldocs" -s Default CustomStyle
+                      COMMENT "Building NaturalDocs documentation..." VERBATIM)
+ELSE(NATDOCS_BIN)
+    MESSAGE(STATUS "\nNaturalDocs not found; building documentation is disabled")
+ENDIF(NATDOCS_BIN)
+
+
+#add an install target here
+IF(APPLE)
+    SET(INCPATH OpenAL)
+ELSE(APPLE)
+    SET(INCPATH AL)
+ENDIF(APPLE)
+
+INSTALL(DIRECTORY "${ALURE_SOURCE_DIR}/docs/html"
+        DESTINATION share/doc/alure
+)
+INSTALL(FILES include/AL/alure.h
+        DESTINATION "include/${INCPATH}"
+)
+IF(BUILD_SHARED)
+    INSTALL(FILES "${ALURE_BINARY_DIR}/alure.pc"
+            DESTINATION "lib${LIB_SUFFIX}/pkgconfig"
+    )
+ENDIF(BUILD_SHARED)
+IF(BUILD_STATIC)
+    INSTALL(FILES "${ALURE_BINARY_DIR}/alure-static.pc"
+            DESTINATION "lib${LIB_SUFFIX}/pkgconfig"
+    )
+ENDIF(BUILD_STATIC)
+IF(BUILD_EXAMPLES AND INSTALL_EXAMPLES)
+    INSTALL(TARGETS alureplay alurestream alurecdplay
+            RUNTIME DESTINATION bin)
+ENDIF(BUILD_EXAMPLES AND INSTALL_EXAMPLES)
+
+
+MESSAGE(STATUS "\n********************** Configured options **********************")
+IF(BUILD_SHARED AND BUILD_STATIC)
+    MESSAGE(STATUS "Building shared, static library")
+ELSEIF(BUILD_SHARED)
+    MESSAGE(STATUS "Building shared library")
+ELSE(BUILD_SHARED AND BUILD_STATIC)
+    MESSAGE(STATUS "Building static library")
+ENDIF(BUILD_SHARED AND BUILD_STATIC)
+IF(BUILD_EXAMPLES AND INSTALL_EXAMPLES)
+    MESSAGE(STATUS "Building and installing examples")
+ELSEIF(BUILD_EXAMPLES)
+    MESSAGE(STATUS "Building (not installing) examples")
+ELSE(BUILD_EXAMPLES AND INSTALL_EXAMPLES)
+    MESSAGE(STATUS "Not building examples")
+ENDIF(BUILD_EXAMPLES AND INSTALL_EXAMPLES)
+MESSAGE(STATUS "")
+IF(HAS_SNDFILE)
+    MESSAGE(STATUS "SndFile support: enabled")
+ELSE(HAS_SNDFILE)
+    MESSAGE(STATUS "SndFile support: disabled")
+ENDIF(HAS_SNDFILE)
+IF(HAS_VORBISFILE)
+    MESSAGE(STATUS "VorbisFile support: enabled")
+ELSE(HAS_VORBISFILE)
+    MESSAGE(STATUS "VorbisFile support: disabled")
+ENDIF(HAS_VORBISFILE)
+IF(HAS_FLAC)
+    MESSAGE(STATUS "FLAC support: enabled")
+ELSE(HAS_FLAC)
+    MESSAGE(STATUS "FLAC support: disabled")
+ENDIF(HAS_FLAC)
+IF(HAS_MPG123)
+    MESSAGE(STATUS "MPG123 support: enabled")
+ELSE(HAS_MPG123)
+    MESSAGE(STATUS "MPG123 support: disabled")
+ENDIF(HAS_MPG123)
+IF(HAS_DUMB)
+    MESSAGE(STATUS "DUMB support: enabled")
+ELSE(HAS_DUMB)
+    MESSAGE(STATUS "DUMB support: disabled")
+ENDIF(HAS_DUMB)
+IF(HAS_MODPLUG)
+    MESSAGE(STATUS "ModPlug support: enabled")
+ELSE(HAS_MODPLUG)
+    MESSAGE(STATUS "ModPlug support: disabled")
+ENDIF(HAS_MODPLUG)
+IF(HAS_FLUIDSYNTH)
+    MESSAGE(STATUS "FluidSynth support: enabled")
+ELSE(HAS_FLUIDSYNTH)
+    MESSAGE(STATUS "FluidSynth support: disabled")
+ENDIF(HAS_FLUIDSYNTH)
+MESSAGE(STATUS "")
diff --git a/COPYING b/COPYING
new file mode 100644 (file)
index 0000000..48a9389
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,19 @@
+Copyright (c) 2009-2010 Chris Robinson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/XCompile.txt b/XCompile.txt
new file mode 100644 (file)
index 0000000..035f1e2
--- /dev/null
@@ -0,0 +1,30 @@
+# Cross-compiling requires CMake 2.6 or newer. To use it from build/, call it
+# like this:
+# cmake .. -DCMAKE_TOOLCHAIN_FILE=../XCompile.txt -DHOST=i686-pc-mingw32
+# Where 'i686-pc-mingw32' is the host prefix for your cross-compiler. If you
+# already have a toolchain file setup, you may use that instead of this file.
+
+# the name of the target operating system
+SET(CMAKE_SYSTEM_NAME Windows)
+
+# which compilers to use for C and C++
+SET(CMAKE_C_COMPILER "${HOST}-gcc")
+SET(CMAKE_CXX_COMPILER "${HOST}-g++")
+
+# here is the target environment located
+SET(CMAKE_FIND_ROOT_PATH "/usr/${HOST}")
+
+# here is where stuff gets installed to
+SET(CMAKE_INSTALL_PREFIX "${CMAKE_FIND_ROOT_PATH}/usr" CACHE STRING "Install path prefix, prepended onto install directories." FORCE)
+
+# adjust the default behaviour of the FIND_XXX() commands:
+# search headers and libraries in the target environment, search 
+# programs in the host environment
+set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+
+# set env vars so that pkg-config will look in the appropriate directory for
+# .pc files (as there seems to be no way to force using ${HOST}-pkg-config)
+set(ENV{PKG_CONFIG_LIBDIR} "${CMAKE_INSTALL_PREFIX}/lib/pkgconfig")
+set(ENV{PKG_CONFIG_PATH} "")
diff --git a/alure-static.pc.in b/alure-static.pc.in
new file mode 100644 (file)
index 0000000..a008a9d
--- /dev/null
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: ALURE
+Description: File-loading and utility functions for OpenAL
+Requires: @PKG_CONFIG_REQUIRES@
+Version: @PACKAGE_VERSION@
+Libs: -L${libdir} -l@LIBNAME@-static @PKG_CONFIG_LIBS@
+Cflags: -I${includedir} -DALURE_STATIC_LIBRARY
diff --git a/alure.pc.in b/alure.pc.in
new file mode 100644 (file)
index 0000000..c992646
--- /dev/null
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: ALURE
+Description: File-loading and utility functions for OpenAL
+Requires: @PKG_CONFIG_REQUIRES@
+Version: @PACKAGE_VERSION@
+Libs: -L${libdir} -l@LIBNAME@ @PKG_CONFIG_LIBS@
+Cflags: -I${includedir}
diff --git a/build/.empty b/build/.empty
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/cmake/CheckCCompilerFlag.cmake b/cmake/CheckCCompilerFlag.cmake
new file mode 100644 (file)
index 0000000..8b2361a
--- /dev/null
@@ -0,0 +1,59 @@
+# - Check if the C source code provided in the SOURCE argument compiles.
+# CHECK_C_SOURCE_COMPILES(SOURCE VAR)
+#
+#  FLAG   - compiler flag to check
+#  VAR    - variable to store whether the source code compiled
+#
+# The following variables may be set before calling this macro to
+# modify the way the check is run:
+#
+#  CMAKE_REQUIRED_FLAGS = string of compile command line flags
+#  CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar)
+#  CMAKE_REQUIRED_INCLUDES = list of include directories
+#  CMAKE_REQUIRED_LIBRARIES = list of libraries to link
+
+MACRO(CHECK_C_COMPILER_FLAG FLAG VAR)
+  IF("${VAR}" MATCHES "^${VAR}$")
+    SET(MACRO_CHECK_FUNCTION_DEFINITIONS
+      "${FLAG} ${CMAKE_REQUIRED_FLAGS}")
+    IF(CMAKE_REQUIRED_LIBRARIES)
+      SET(CHECK_C_COMPILER_FLAG_ADD_LIBRARIES
+        "-DLINK_LIBRARIES:STRING=${CMAKE_REQUIRED_LIBRARIES}")
+    ELSE(CMAKE_REQUIRED_LIBRARIES)
+      SET(CHECK_C_COMPILER_FLAG_ADD_LIBRARIES)
+    ENDIF(CMAKE_REQUIRED_LIBRARIES)
+    IF(CMAKE_REQUIRED_INCLUDES)
+      SET(CHECK_C_COMPILER_FLAG_ADD_INCLUDES
+        "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}")
+    ELSE(CMAKE_REQUIRED_INCLUDES)
+      SET(CHECK_C_COMPILER_FLAG_ADD_INCLUDES)
+    ENDIF(CMAKE_REQUIRED_INCLUDES)
+    FILE(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.c"
+      "int main() {return 0;}\n")
+
+    MESSAGE(STATUS "Checking if C compiler supports ${FLAG}")
+    TRY_COMPILE(${VAR}
+      ${CMAKE_BINARY_DIR}
+      ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.c
+      COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
+      CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS}
+      "${CHECK_C_COMPILER_FLAG_ADD_LIBRARIES}"
+      "${CHECK_C_COMPILER_FLAG_ADD_INCLUDES}"
+      OUTPUT_VARIABLE OUTPUT)
+    IF(${VAR})
+      SET(${VAR} 1 CACHE INTERNAL "Test ${VAR}")
+      MESSAGE(STATUS "Checking if C compiler supports ${FLAG} - Success")
+      FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
+        "Performing C SOURCE FILE Test ${VAR} succeded with the following output:\n"
+        "${OUTPUT}\n"
+        "Source file was:\n${SOURCE}\n")
+    ELSE(${VAR})
+      MESSAGE(STATUS "Checking if C compiler supports ${FLAG} - Failed")
+      SET(${VAR} "" CACHE INTERNAL "Test ${VAR}")
+      FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
+        "Performing C SOURCE FILE Test ${VAR} failed with the following output:\n"
+        "${OUTPUT}\n"
+        "Source file was:\n${SOURCE}\n")
+    ENDIF(${VAR})
+  ENDIF("${VAR}" MATCHES "^${VAR}$")
+ENDMACRO(CHECK_C_COMPILER_FLAG)
diff --git a/cmake/CheckFileOffsetBits.c b/cmake/CheckFileOffsetBits.c
new file mode 100644 (file)
index 0000000..de98296
--- /dev/null
@@ -0,0 +1,9 @@
+#include <sys/types.h>
+
+#define KB ((off_t)(1024))
+#define MB ((off_t)(KB*1024))
+#define GB ((off_t)(MB*1024))
+int tb[((GB+GB+GB) > GB) ? 1 : -1];
+
+int main()
+{ return 0; }
diff --git a/cmake/CheckFileOffsetBits.cmake b/cmake/CheckFileOffsetBits.cmake
new file mode 100644 (file)
index 0000000..8b549b6
--- /dev/null
@@ -0,0 +1,39 @@
+# - Check if the _FILE_OFFSET_BITS macro is needed for large files
+# CHECK_FILE_OFFSET_BITS()
+#
+# The following variables may be set before calling this macro to
+# modify the way the check is run:
+#
+#  CMAKE_REQUIRED_FLAGS = string of compile command line flags
+#  CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar)
+#  CMAKE_REQUIRED_INCLUDES = list of include directories
+# Copyright (c) 2009, Chris Robinson
+#
+# Redistribution and use is allowed according to the terms of the LGPL license.
+
+
+MACRO(CHECK_FILE_OFFSET_BITS)
+
+  IF(NOT DEFINED _FILE_OFFSET_BITS)
+    MESSAGE(STATUS "Checking _FILE_OFFSET_BITS for large files")
+    TRY_COMPILE(__WITHOUT_FILE_OFFSET_BITS_64
+      ${CMAKE_BINARY_DIR}
+      ${CMAKE_SOURCE_DIR}/cmake/CheckFileOffsetBits.c
+      COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS})
+    IF(NOT __WITHOUT_FILE_OFFSET_BITS_64)
+      TRY_COMPILE(__WITH_FILE_OFFSET_BITS_64
+        ${CMAKE_BINARY_DIR}
+        ${CMAKE_SOURCE_DIR}/cmake/CheckFileOffsetBits.c
+        COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} -D_FILE_OFFSET_BITS=64)
+    ENDIF(NOT __WITHOUT_FILE_OFFSET_BITS_64)
+
+    IF(NOT __WITHOUT_FILE_OFFSET_BITS_64 AND __WITH_FILE_OFFSET_BITS_64)
+      SET(_FILE_OFFSET_BITS 64 CACHE INTERNAL "_FILE_OFFSET_BITS macro needed for large files")
+      MESSAGE(STATUS "Checking _FILE_OFFSET_BITS for large files - 64")
+    ELSE(NOT __WITHOUT_FILE_OFFSET_BITS_64 AND __WITH_FILE_OFFSET_BITS_64)
+      SET(_FILE_OFFSET_BITS "" CACHE INTERNAL "_FILE_OFFSET_BITS macro needed for large files")
+      MESSAGE(STATUS "Checking _FILE_OFFSET_BITS for large files - not needed")
+    ENDIF(NOT __WITHOUT_FILE_OFFSET_BITS_64 AND __WITH_FILE_OFFSET_BITS_64)
+  ENDIF(NOT DEFINED _FILE_OFFSET_BITS)
+
+ENDMACRO(CHECK_FILE_OFFSET_BITS)
\ No newline at end of file
diff --git a/cmake/CheckSharedFunctionExists.cmake b/cmake/CheckSharedFunctionExists.cmake
new file mode 100644 (file)
index 0000000..4980eff
--- /dev/null
@@ -0,0 +1,92 @@
+# - Check if a symbol exists as a function, variable, or macro
+# CHECK_SYMBOL_EXISTS(<symbol> <files> <variable>)
+#
+# Check that the <symbol> is available after including given header
+# <files> and store the result in a <variable>.  Specify the list
+# of files in one argument as a semicolon-separated list.
+#
+# If the header files define the symbol as a macro it is considered
+# available and assumed to work.  If the header files declare the
+# symbol as a function or variable then the symbol must also be
+# available for linking.  If the symbol is a type or enum value
+# it will not be recognized (consider using CheckTypeSize or
+# CheckCSourceCompiles).
+#
+# The following variables may be set before calling this macro to
+# modify the way the check is run:
+#
+#  CMAKE_REQUIRED_FLAGS = string of compile command line flags
+#  CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar)
+#  CMAKE_REQUIRED_INCLUDES = list of include directories
+#  CMAKE_REQUIRED_LIBRARIES = list of libraries to link
+
+#=============================================================================
+# Copyright 2003-2011 Kitware, Inc.
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distribute this file outside of CMake, substitute the full
+#  License text for the above reference.)
+
+MACRO(CHECK_SHARED_FUNCTION_EXISTS SYMBOL FILES LIBRARY LOCATION VARIABLE)
+  IF("${VARIABLE}" MATCHES "^${VARIABLE}$")
+    SET(CMAKE_CONFIGURABLE_FILE_CONTENT "/* */\n")
+    SET(MACRO_CHECK_SYMBOL_EXISTS_FLAGS ${CMAKE_REQUIRED_FLAGS})
+    IF(CMAKE_REQUIRED_LIBRARIES)
+      SET(CHECK_SYMBOL_EXISTS_LIBS 
+        "-DLINK_LIBRARIES:STRING=${CMAKE_REQUIRED_LIBRARIES};${LIBRARY}")
+    ELSE(CMAKE_REQUIRED_LIBRARIES)
+      SET(CHECK_SYMBOL_EXISTS_LIBS
+        "-DLINK_LIBRARIES:STRING=${LIBRARY}")
+    ENDIF(CMAKE_REQUIRED_LIBRARIES)
+    IF(CMAKE_REQUIRED_INCLUDES)
+      SET(CMAKE_SYMBOL_EXISTS_INCLUDES
+        "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}")
+    ELSE(CMAKE_REQUIRED_INCLUDES)
+      SET(CMAKE_SYMBOL_EXISTS_INCLUDES)
+    ENDIF(CMAKE_REQUIRED_INCLUDES)
+    FOREACH(FILE ${FILES})
+      SET(CMAKE_CONFIGURABLE_FILE_CONTENT
+        "${CMAKE_CONFIGURABLE_FILE_CONTENT}#include <${FILE}>\n")
+    ENDFOREACH(FILE)
+    SET(CMAKE_CONFIGURABLE_FILE_CONTENT
+      "${CMAKE_CONFIGURABLE_FILE_CONTENT}\nvoid cmakeRequireSymbol(int dummy,...){(void)dummy;}\nint main()\n{\n  cmakeRequireSymbol(0,&${SYMBOL});\n  return 0;\n}\n")
+
+    CONFIGURE_FILE("${CMAKE_ROOT}/Modules/CMakeConfigurableFile.in"
+      "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckSymbolExists.c" @ONLY)
+
+    MESSAGE(STATUS "Looking for ${SYMBOL} in ${LIBRARY}")
+    TRY_COMPILE(${VARIABLE}
+      ${CMAKE_BINARY_DIR}
+      ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckSymbolExists.c
+      COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
+      CMAKE_FLAGS 
+      -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_SYMBOL_EXISTS_FLAGS}
+      -DLINK_DIRECTORIES:STRING=${LOCATION}
+      "${CHECK_SYMBOL_EXISTS_LIBS}"
+      "${CMAKE_SYMBOL_EXISTS_INCLUDES}"
+      OUTPUT_VARIABLE OUTPUT)
+    IF(${VARIABLE})
+      MESSAGE(STATUS "Looking for ${SYMBOL} in ${LIBRARY} - found")
+      SET(${VARIABLE} 1 CACHE INTERNAL "Have symbol ${SYMBOL} in ${LIBRARY}")
+      FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log 
+        "Determining if the ${SYMBOL} "
+        "exist in ${LIBRARY} passed with the following output:\n"
+        "${OUTPUT}\nFile ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckSymbolExists.c:\n"
+        "${CMAKE_CONFIGURABLE_FILE_CONTENT}\n")
+    ELSE(${VARIABLE})
+      MESSAGE(STATUS "Looking for ${SYMBOL} in ${LIBRARY} - not found.")
+      SET(${VARIABLE} "" CACHE INTERNAL "Have symbol ${SYMBOL} in ${LIBRARY}")
+      FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log 
+        "Determining if the ${SYMBOL} "
+        "exist in ${LIBRARY} failed with the following output:\n"
+        "${OUTPUT}\nFile ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckSymbolExists.c:\n"
+        "${CMAKE_CONFIGURABLE_FILE_CONTENT}\n")
+    ENDIF(${VARIABLE})
+  ENDIF("${VARIABLE}" MATCHES "^${VARIABLE}$")
+ENDMACRO(CHECK_SHARED_FUNCTION_EXISTS)
diff --git a/cmake/FindFLAC.cmake b/cmake/FindFLAC.cmake
new file mode 100644 (file)
index 0000000..e0b0839
--- /dev/null
@@ -0,0 +1,78 @@
+# Copyright (c) 2009, Whispersoft s.r.l.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Whispersoft s.r.l. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Finds FLAC library
+#
+#  FLAC_INCLUDE_DIR - where to find flac.h, etc.
+#  FLAC_LIBRARIES   - List of libraries when using FLAC.
+#  FLAC_FOUND       - True if FLAC found.
+#
+
+if (FLAC_INCLUDE_DIR)
+  # Already in cache, be silent
+  set(FLAC_FIND_QUIETLY TRUE)
+endif (FLAC_INCLUDE_DIR)
+
+find_path(FLAC_INCLUDE_DIR FLAC/all.h
+  /opt/local/include
+  /usr/local/include
+  /usr/include
+)
+
+set(FLAC_NAMES FLAC)
+find_library(FLAC_LIBRARY
+  NAMES ${FLAC_NAMES}
+  PATHS /usr/lib /usr/local/lib /opt/local/lib
+)
+
+if (FLAC_INCLUDE_DIR AND FLAC_LIBRARY)
+   set(FLAC_FOUND TRUE)
+   set( FLAC_LIBRARIES ${FLAC_LIBRARY} )
+else (FLAC_INCLUDE_DIR AND FLAC_LIBRARY)
+   set(FLAC_FOUND FALSE)
+   set(FLAC_LIBRARIES)
+endif (FLAC_INCLUDE_DIR AND FLAC_LIBRARY)
+
+if (FLAC_FOUND)
+   if (NOT FLAC_FIND_QUIETLY)
+      message(STATUS "Found FLAC: ${FLAC_LIBRARY}")
+   endif (NOT FLAC_FIND_QUIETLY)
+else (FLAC_FOUND)
+   if (FLAC_FIND_REQUIRED)
+      message(STATUS "Looked for FLAC libraries named ${FLAC_NAMES}.")
+      message(STATUS "Include file detected: [${FLAC_INCLUDE_DIR}].")
+      message(STATUS "Lib file detected: [${FLAC_LIBRARY}].")
+      message(FATAL_ERROR "=========> Could NOT find FLAC library")
+   endif (FLAC_FIND_REQUIRED)
+endif (FLAC_FOUND)
+
+mark_as_advanced(
+  FLAC_LIBRARY
+  FLAC_INCLUDE_DIR
+  )
diff --git a/cmake/FindOggVorbis.cmake b/cmake/FindOggVorbis.cmake
new file mode 100644 (file)
index 0000000..0269ce7
--- /dev/null
@@ -0,0 +1,67 @@
+# - Try to find the OggVorbis libraries
+# Once done this will define
+#
+#  OGGVORBIS_FOUND - system has OggVorbis
+#  OGGVORBIS_VERSION - set either to 1 or 2
+#  OGGVORBIS_INCLUDE_DIRS - the OggVorbis include directories
+#  OGGVORBIS_LIBRARIES - The libraries needed to use OggVorbis
+#  OGG_LIBRARY         - The Ogg library
+#  VORBIS_LIBRARY      - The Vorbis library
+#  VORBISFILE_LIBRARY  - The VorbisFile library
+#  VORBISENC_LIBRARY   - The VorbisEnc library
+
+# Copyright (c) 2006, Richard Laerkaeng, <richard@goteborg.utfors.se>
+#
+# Redistribution and use is allowed according to the terms of the BSD license.
+# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
+
+
+include (CheckFunctionExists)
+
+find_path(VORBIS_INCLUDE_DIR vorbis/vorbisfile.h)
+find_path(OGG_INCLUDE_DIR ogg/ogg.h)
+
+find_library(OGG_LIBRARY NAMES ogg)
+find_library(VORBIS_LIBRARY NAMES vorbis)
+find_library(VORBISFILE_LIBRARY NAMES vorbisfile)
+find_library(VORBISENC_LIBRARY NAMES vorbisenc)
+
+mark_as_advanced(VORBIS_INCLUDE_DIR OGG_INCLUDE_DIR
+                 OGG_LIBRARY VORBIS_LIBRARY VORBISFILE_LIBRARY VORBISENC_LIBRARY)
+
+
+if(VORBIS_INCLUDE_DIR AND VORBIS_LIBRARY AND VORBISFILE_LIBRARY AND VORBISENC_LIBRARY)
+   set(OGGVORBIS_FOUND TRUE)
+
+   set(OGGVORBIS_LIBRARIES ${OGG_LIBRARY} ${VORBIS_LIBRARY} ${VORBISFILE_LIBRARY} ${VORBISENC_LIBRARY})
+   set(OGGVORBIS_INCLUDE_DIRS ${OGG_INCLUDE_DIR} ${VORBIS_INCLUDE_DIR})
+
+   set(_CMAKE_REQUIRED_LIBRARIES_TMP ${CMAKE_REQUIRED_LIBRARIES})
+   set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ${OGGVORBIS_LIBRARIES})
+   check_function_exists(vorbis_bitrate_addblock HAVE_LIBVORBISENC2)
+   set(CMAKE_REQUIRED_LIBRARIES ${_CMAKE_REQUIRED_LIBRARIES_TMP})
+
+   if(HAVE_LIBVORBISENC2)
+      set(OGGVORBIS_VERSION 2)
+   else(HAVE_LIBVORBISENC2)
+      set(OGGVORBIS_VERSION 1)
+   endif(HAVE_LIBVORBISENC2)
+
+else(VORBIS_INCLUDE_DIR AND VORBIS_LIBRARY AND VORBISFILE_LIBRARY AND VORBISENC_LIBRARY)
+   set(OGGVORBIS_VERSION)
+   set(OGGVORBIS_FOUND FALSE)
+endif(VORBIS_INCLUDE_DIR AND VORBIS_LIBRARY AND VORBISFILE_LIBRARY AND VORBISENC_LIBRARY)
+
+
+if(OGGVORBIS_FOUND)
+   if(NOT OggVorbis_FIND_QUIETLY)
+      message(STATUS "Found OggVorbis: ${OGGVORBIS_LIBRARIES}")
+   endif(NOT OggVorbis_FIND_QUIETLY)
+else(OGGVORBIS_FOUND)
+   if(OggVorbis_FIND_REQUIRED)
+      message(FATAL_ERROR "Could NOT find OggVorbis libraries")
+   endif(OggVorbis_FIND_REQUIRED)
+   if(NOT OggVorbis_FIND_QUITELY)
+      message(STATUS "Could NOT find OggVorbis libraries")
+   endif(NOT OggVorbis_FIND_QUITELY)
+endif(OGGVORBIS_FOUND)
diff --git a/cmake/FindOpenAL.cmake b/cmake/FindOpenAL.cmake
new file mode 100644 (file)
index 0000000..3d8a664
--- /dev/null
@@ -0,0 +1,113 @@
+# Locate OpenAL
+# This module defines
+# OPENAL_LIBRARY
+# OPENAL_FOUND, if false, do not try to link to OpenAL 
+# OPENAL_INCLUDE_DIR, where to find the headers
+#
+# $OPENALDIR is an environment variable that would
+# correspond to the ./configure --prefix=$OPENALDIR
+# used in building OpenAL.
+#
+# Created by Eric Wing. This was influenced by the FindSDL.cmake module.
+
+#=============================================================================
+# Copyright 2005-2009 Kitware, Inc.
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distribute this file outside of CMake, substitute the full
+#  License text for the above reference.)
+
+# For Windows, OpenAL would be included like
+# #include <al.h>
+# For Apple, you would include it like
+# #include <OpenAL/al.h>
+# Other systems include it like
+# #include <AL/al.h>
+# The reason for this is that Creative Labs does not by default put their
+# headers in AL/ for Windows, and other systems follow the OpenGL convention
+# (OpenAL/ for OSX, and AL/ for Linux and other Unixes).
+# 
+# For Windows, Creative Labs seems to have added a registry key for their 
+# OpenAL 1.1 installer. I have added that key to the list of search paths,
+# however, the key looks like it could be a little fragile depending on 
+# if they decide to change the 1.00.0000 number for bug fix releases.
+# Also, they seem to have laid down groundwork for multiple library platforms
+# which puts the library in an extra subdirectory. Currently there is only
+# Win32 and I have hardcoded that here. This may need to be adjusted as 
+# platforms are introduced.
+# The OpenAL 1.0 installer doesn't seem to have a useful key I can use.
+# I do not know if the Nvidia OpenAL SDK has a registry key.
+# 
+# For OSX, remember that OpenAL was added by Apple in 10.4 (Tiger). 
+# To support the framework, I originally wrote special framework detection 
+# code in this module which I have now removed with CMake's introduction
+# of native support for frameworks.
+# In addition, OpenAL is open source, and it is possible to compile on Panther. 
+# Furthermore, due to bugs in the initial OpenAL release, and the 
+# transition to OpenAL 1.1, it is common to need to override the built-in
+# framework. 
+# Per my request, CMake should search for frameworks first in
+# the following order:
+# ~/Library/Frameworks/OpenAL.framework/Headers
+# /Library/Frameworks/OpenAL.framework/Headers
+# /System/Library/Frameworks/OpenAL.framework/Headers
+#
+# On OSX, this will prefer the Framework version (if found) over others.
+# People will have to manually change the cache values of 
+# OPENAL_LIBRARY to override this selection or set the CMake environment
+# CMAKE_INCLUDE_PATH to modify the search paths.
+
+IF(WIN32)
+    SET(AL_HEADER_PREFIX "")
+ELSEIF(APPLE)
+    SET(AL_HEADER_PREFIX "OpenAL/")
+ELSE(WIN32)
+    SET(AL_HEADER_PREFIX "AL/")
+ENDIF(WIN32)
+
+FIND_PATH(OPENAL_INCLUDE_DIR "${AL_HEADER_PREFIX}al.h"
+  HINTS
+  $ENV{OPENALDIR}
+  PATH_SUFFIXES include include/AL
+  PATHS
+  ~/Library/Frameworks
+  /Library/Frameworks
+  /usr/local
+  /usr
+  /sw # Fink
+  /opt/local # DarwinPorts
+  /opt/csw # Blastwave
+  /opt
+  [HKEY_LOCAL_MACHINE\\SOFTWARE\\Creative\ Labs\\OpenAL\ 1.1\ Software\ Development\ Kit\\1.00.0000;InstallDir]
+)
+
+FIND_LIBRARY(OPENAL_LIBRARY 
+  NAMES OpenAL al openal OpenAL32
+  HINTS
+  $ENV{OPENALDIR}
+  PATH_SUFFIXES lib64 lib libs64 libs libs/Win32 libs/Win64
+  PATHS
+  ~/Library/Frameworks
+  /Library/Frameworks
+  /usr/local
+  /usr
+  /sw
+  /opt/local
+  /opt/csw
+  /opt
+  [HKEY_LOCAL_MACHINE\\SOFTWARE\\Creative\ Labs\\OpenAL\ 1.1\ Software\ Development\ Kit\\1.00.0000;InstallDir]
+)
+
+
+# handle the QUIETLY and REQUIRED arguments and set OPENAL_FOUND to TRUE if
+# all listed variables are TRUE
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(OpenAL  DEFAULT_MSG  OPENAL_LIBRARY OPENAL_INCLUDE_DIR)
+
+MARK_AS_ADVANCED(OPENAL_LIBRARY OPENAL_INCLUDE_DIR)
diff --git a/cmake/FindSndFile.cmake b/cmake/FindSndFile.cmake
new file mode 100644 (file)
index 0000000..622914c
--- /dev/null
@@ -0,0 +1,49 @@
+# - Try to find SndFile
+# Once done this will define
+#
+#  SNDFILE_FOUND - system has SndFile
+#  SNDFILE_INCLUDE_DIRS - the SndFile include directory
+#  SNDFILE_LIBRARIES - Link these to use SndFile
+#
+#  Copyright Â© 2006  Wengo
+#  Copyright Â© 2009 Guillaume Martres
+#
+#  Redistribution and use is allowed according to the terms of the New
+#  BSD license.
+#  For details see the accompanying COPYING-CMAKE-SCRIPTS file.
+#
+
+find_path(SNDFILE_INCLUDE_DIR
+    NAMES
+      sndfile.h
+    PATHS
+      /usr/include
+      /usr/local/include
+      /opt/local/include
+      /sw/include
+)
+
+find_library(SNDFILE_LIBRARY
+    NAMES
+      sndfile sndfile-1
+    PATHS
+      /usr/lib
+      /usr/local/lib
+      /opt/local/lib
+      /sw/lib
+)
+
+set(SNDFILE_INCLUDE_DIRS
+    ${SNDFILE_INCLUDE_DIR}
+)
+set(SNDFILE_LIBRARIES
+    ${SNDFILE_LIBRARY}
+)
+
+INCLUDE(FindPackageHandleStandardArgs)
+# handle the QUIETLY and REQUIRED arguments and set SNDFILE_FOUND to TRUE if
+# all listed variables are TRUE
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(SndFile DEFAULT_MSG SNDFILE_LIBRARY SNDFILE_INCLUDE_DIR)
+
+# show the SNDFILE_INCLUDE_DIRS and SNDFILE_LIBRARIES variables only in the advanced view
+mark_as_advanced(SNDFILE_INCLUDE_DIRS SNDFILE_LIBRARIES)
diff --git a/config.h.in b/config.h.in
new file mode 100644 (file)
index 0000000..284e5bc
--- /dev/null
@@ -0,0 +1,50 @@
+/* API declaration export attribute */
+#ifndef ALURE_STATIC_LIBRARY
+#define ALURE_API ${EXPORT_DECL}
+#endif
+
+/* Define to the version of the library being built */
+#define ALURE_VER_MAJOR ${LIB_MAJOR_VERSION}
+#define ALURE_VER_MINOR ${LIB_MINOR_VERSION}
+
+/* Define if we have GCC's constructor attribute */
+#cmakedefine HAVE_GCC_CONSTRUCTOR
+
+/* Define if we have GCC's visibility attribute */
+#cmakedefine HAVE_GCC_VISIBILITY
+
+/* Define if we have windows.h */
+#cmakedefine HAVE_WINDOWS_H
+
+/* Define if we have pthread_np.h */
+#cmakedefine HAVE_PTHREAD_NP_H
+
+/* Define if we have dlfcn.h */
+#cmakedefine HAVE_DLFCN_H
+
+/* Define if we have sys/types.h */
+#cmakedefine HAVE_SYS_TYPES_H
+
+/* Define if we have sys/wait.h */
+#cmakedefine HAVE_SYS_WAIT_H
+
+/* Define if we have signal.h */
+#cmakedefine HAVE_SIGNAL_H
+
+/* Define if we have nanosleep */
+#cmakedefine HAVE_NANOSLEEP
+
+/* Define if we have fseeko */
+#cmakedefine HAVE_FSEEKO
+
+/* Define if we have _fseeki64 */
+#cmakedefine HAVE__FSEEKI64
+
+/* Define the supported backends */
+#cmakedefine HAS_VORBISFILE
+#cmakedefine HAS_FLAC
+#cmakedefine HAS_SNDFILE
+#cmakedefine HAS_FLUIDSYNTH
+#cmakedefine HAS_DUMB
+#cmakedefine HAS_MODPLUG
+#cmakedefine HAS_MPG123
diff --git a/docs/html/files/alure-cpp.html b/docs/html/files/alure-cpp.html
new file mode 100644 (file)
index 0000000..e1d7811
--- /dev/null
@@ -0,0 +1,60 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+
+<html><head><title>Main and Miscellanious - ALURE</title><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script><script language=JavaScript src="../javascript/searchdata.js"></script></head><body class="ContentPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
+if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
+
+<!--  Generated by Natural Docs, version 1.4 -->
+<!--  http://www.naturaldocs.org  -->
+
+<!-- saved from url=(0026)http://www.naturaldocs.org -->
+
+
+
+
+<div id=Content><div class="CSection"><div class=CTopic id=MainTopic><h1 class=CTitle><a name="Main_and_Miscellanious"></a>Main and Miscellanious</h1><div class=CBody><!--START_ND_SUMMARY--><div class=Summary><div class=STitle>Summary</div><div class=SBorder><table border=0 cellspacing=0 cellpadding=0 class=STable><tr class="SMain"><td class=SEntry><a href="#Main_and_Miscellanious" >Main and Miscellanious</a></td><td class=SDescription></td></tr><tr class="SGroup SIndent1"><td class=SEntry><a href="#Functions" >Functions</a></td><td class=SDescription></td></tr><tr class="SFunction SIndent2 SMarked"><td class=SEntry><a href="#alureGetVersion" id=link1 onMouseOver="ShowTip(event, 'tt1', 'link1')" onMouseOut="HideTip('tt1')">alureGetVersion</a></td><td class=SDescription>Stores the major and minor version of the library. </td></tr><tr class="SFunction SIndent2"><td class=SEntry><a href="#alureGetErrorString" id=link2 onMouseOver="ShowTip(event, 'tt2', 'link2')" onMouseOut="HideTip('tt2')">alureGetErrorString</a></td><td class=SDescription>Returns a string describing the last error encountered.</td></tr><tr class="SFunction SIndent2 SMarked"><td class=SEntry><a href="#alureGetDeviceNames" id=link3 onMouseOver="ShowTip(event, 'tt3', 'link3')" onMouseOut="HideTip('tt3')">alureGetDeviceNames</a></td><td class=SDescription>Gets an array of device name strings from OpenAL. </td></tr><tr class="SFunction SIndent2"><td class=SEntry><a href="#alureFreeDeviceNames" id=link4 onMouseOver="ShowTip(event, 'tt4', 'link4')" onMouseOut="HideTip('tt4')">alureFreeDeviceNames</a></td><td class=SDescription>Frees the device name array returned from alureGetDeviceNames.</td></tr><tr class="SFunction SIndent2 SMarked"><td class=SEntry><a href="#alureInitDevice" id=link5 onMouseOver="ShowTip(event, 'tt5', 'link5')" onMouseOut="HideTip('tt5')">alureInitDevice</a></td><td class=SDescription>Opens the named device, creates a context with the given attributes, and sets that context as current. </td></tr><tr class="SFunction SIndent2"><td class=SEntry><a href="#alureShutdownDevice" id=link6 onMouseOver="ShowTip(event, 'tt6', 'link6')" onMouseOut="HideTip('tt6')">alureShutdownDevice</a></td><td class=SDescription>Destroys the current context and closes its associated device.</td></tr><tr class="SFunction SIndent2 SMarked"><td class=SEntry><a href="#alureGetSampleFormat" id=link7 onMouseOver="ShowTip(event, 'tt7', 'link7')" onMouseOut="HideTip('tt7')">alureGetSampleFormat</a></td><td class=SDescription>Retrieves an OpenAL format for the given sample format. </td></tr><tr class="SFunction SIndent2"><td class=SEntry><a href="#alureInstallDecodeCallbacks" id=link8 onMouseOver="ShowTip(event, 'tt8', 'link8')" onMouseOut="HideTip('tt8')">alureInstallDecodeCallbacks</a></td><td class=SDescription>Installs callbacks to enable ALURE to handle more file types. </td></tr><tr class="SFunction SIndent2 SMarked"><td class=SEntry><a href="#alureSleep" id=link9 onMouseOver="ShowTip(event, 'tt9', 'link9')" onMouseOut="HideTip('tt9')">alureSleep</a></td><td class=SDescription>Rests the calling thread for the given number of seconds.</td></tr><tr class="SFunction SIndent2"><td class=SEntry><a href="#alureGetProcAddress" id=link10 onMouseOver="ShowTip(event, 'tt10', 'link10')" onMouseOut="HideTip('tt10')">alureGetProcAddress</a></td><td class=SDescription>Returns a pointer for the named ALURE function.</td></tr></table></div></div><!--END_ND_SUMMARY--></div></div></div>
+
+<div class="CGroup"><div class=CTopic><h3 class=CTitle><a name="Functions"></a>Functions</h3></div></div>
+
+<div class="CFunction"><div class=CTopic><h3 class=CTitle><a name="alureGetVersion"></a>alureGetVersion</h3><div class=CBody><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API void ALURE_APIENTRY alureGetVersion(</td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>major,</td></tr><tr><td></td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>minor</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote><p>Stores the major and minor version of the library.&nbsp; If either major or minor are NULL, that value is not provided.</p></div></div></div>
+
+<div class="CFunction"><div class=CTopic><h3 class=CTitle><a name="alureGetErrorString"></a>alureGetErrorString</h3><div class=CBody><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API const ALchar* ALURE_APIENTRY alureGetErrorString(</td><td class=PParameter nowrap>void</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote><p>Returns a string describing the last error encountered.</p></div></div></div>
+
+<div class="CFunction"><div class=CTopic><h3 class=CTitle><a name="alureGetDeviceNames"></a>alureGetDeviceNames</h3><div class=CBody><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API const ALCchar** ALURE_APIENTRY alureGetDeviceNames(</td><td class=PType nowrap>ALCboolean&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap>all,</td></tr><tr><td></td><td class=PType nowrap>ALCsizei&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>count</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote><p>Gets an array of device name strings from OpenAL.&nbsp; This encapsulates AL_ENUMERATE_ALL_EXT (if supported and &lsquo;all&rsquo; is true) and standard enumeration, with &lsquo;count&rsquo; being set to the number of returned device names.</p><h4 class=CHeading>Returns</h4><p>An array of device name strings, or NULL on error.</p><h4 class=CHeading>See Also</h4><p><a href="#alureFreeDeviceNames" class=LFunction id=link11 onMouseOver="ShowTip(event, 'tt4', 'link11')" onMouseOut="HideTip('tt4')">alureFreeDeviceNames</a></p></div></div></div>
+
+<div class="CFunction"><div class=CTopic><h3 class=CTitle><a name="alureFreeDeviceNames"></a>alureFreeDeviceNames</h3><div class=CBody><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALvoid ALURE_APIENTRY alureFreeDeviceNames(</td><td class=PTypePrefix nowrap>const&nbsp;</td><td class=PType nowrap>ALCchar&nbsp;</td><td class=PParameterPrefix nowrap>**</td><td class=PParameter nowrap>names</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote><p>Frees the device name array returned from alureGetDeviceNames.</p><h4 class=CHeading>See Also</h4><p><a href="#alureGetDeviceNames" class=LFunction id=link12 onMouseOver="ShowTip(event, 'tt3', 'link12')" onMouseOut="HideTip('tt3')">alureGetDeviceNames</a></p></div></div></div>
+
+<div class="CFunction"><div class=CTopic><h3 class=CTitle><a name="alureInitDevice"></a>alureInitDevice</h3><div class=CBody><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALboolean ALURE_APIENTRY alureInitDevice(</td><td class=PTypePrefix nowrap>const&nbsp;</td><td class=PType nowrap>ALCchar&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>name,</td></tr><tr><td></td><td class=PTypePrefix nowrap>const&nbsp;</td><td class=PType nowrap>ALCint&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>attribs</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote><p>Opens the named device, creates a context with the given attributes, and sets that context as current.&nbsp; The name and attribute list would be the same as what&rsquo;s passed to alcOpenDevice and alcCreateContext respectively.</p><h4 class=CHeading>Returns</h4><p>AL_FALSE on error.</p><h4 class=CHeading>See Also</h4><p><a href="#alureShutdownDevice" class=LFunction id=link13 onMouseOver="ShowTip(event, 'tt6', 'link13')" onMouseOut="HideTip('tt6')">alureShutdownDevice</a></p></div></div></div>
+
+<div class="CFunction"><div class=CTopic><h3 class=CTitle><a name="alureShutdownDevice"></a>alureShutdownDevice</h3><div class=CBody><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALboolean ALURE_APIENTRY alureShutdownDevice(</td><td class=PParameter nowrap>void</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote><p>Destroys the current context and closes its associated device.</p><h4 class=CHeading>Returns</h4><p>AL_FALSE on error.</p><h4 class=CHeading>See Also</h4><p><a href="#alureInitDevice" class=LFunction id=link14 onMouseOver="ShowTip(event, 'tt5', 'link14')" onMouseOut="HideTip('tt5')">alureInitDevice</a></p></div></div></div>
+
+<div class="CFunction"><div class=CTopic><h3 class=CTitle><a name="alureGetSampleFormat"></a>alureGetSampleFormat</h3><div class=CBody><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALenum ALURE_APIENTRY alureGetSampleFormat(</td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameter nowrap>channels,</td></tr><tr><td></td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameter nowrap>bits,</td></tr><tr><td></td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameter nowrap>floatbits</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote><p>Retrieves an OpenAL format for the given sample format.&nbsp; If bits is non-0, floatbits must be 0, and if floatbits is non-0, bits must be 0.&nbsp; The application should not rely on any particular format enum being returned as it is dependant on the available extensions.&nbsp; The returned format will be valid for the current context.&nbsp; Requires an active context.</p><h4 class=CHeading>Returns</h4><p>An OpenAL format enum for the given sample format, or AL_NONE if one can&rsquo;t be found.</p></div></div></div>
+
+<div class="CFunction"><div class=CTopic><h3 class=CTitle><a name="alureInstallDecodeCallbacks"></a>alureInstallDecodeCallbacks</h3><div class=CBody><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters colspan=4>ALURE_API ALboolean ALURE_APIENTRY alureInstallDecodeCallbacks(</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALint&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>index,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>void&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>(*open_file)(const ALchar *filename),</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>void&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>(*open_memory)(const ALubyte *data, ALuint length),</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALboolean&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>(*get_format)(void *instance, ALenum *format, ALuint *samplerate, ALuint *blocksize),</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>(*decode)(void *instance, ALubyte *data, ALuint bytes),</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALboolean&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>(*rewind)(void *instance),</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>void&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>(*close)(void *instance)</td></tr><tr><td class=PAfterParameters colspan=4>)</td></tr></table></td></tr></table></blockquote><p>Installs callbacks to enable ALURE to handle more file types.&nbsp; The index is the order that each given set of callbacks will be tried, starting at the most negative number (INT_MIN) and going up.&nbsp; Negative indices will be tried before the built-in decoders, and positive indices will be tried after.&nbsp; Installing callbacks onto the same index multiple times will remove the previous callbacks, and removing old callbacks won&rsquo;t affect any opened files using them (they&rsquo;ll continue to use the old functions until properly closed, although newly opened files will use the new ones).&nbsp; Passing NULL for all callbacks is a valid way to remove an installed set, otherwise certain callbacks must be specified.&nbsp; Callbacks that are not specified will assume failure.</p><h4 class=CHeading>Parameters</h4><table border=0 cellspacing=0 cellpadding=0 class=CDescriptionList><tr><td class=CDLEntry>open_file</td><td class=CDLDescription>This callback is expected to open the named file and prepare it for decoding.&nbsp; If the callbacks cannot decode the file, NULL should be returned to indicate failure.&nbsp; Upon success, a non-NULL handle must be returned, which will be used as a unique identifier for the decoder instance.&nbsp; This callback is required if open_memory is not specified.</td></tr><tr><td class=CDLEntry>open_memory</td><td class=CDLDescription>This callback behaves the same as open_file, except it takes a memory segment for input instead of a filename.&nbsp; The given memory will remain valid while the instance is open.&nbsp; This callback is required if open_file is not specified.</td></tr><tr><td class=CDLEntry>get_format</td><td class=CDLDescription>This callback is used to retrieve the format of the decoded data for the given instance.&nbsp; It is the responsibility of the function to make sure the returned format is valid for the current AL context (eg. don&rsquo;t return AL_FORMAT_QUAD16 if the AL_EXT_MCFORMATS extension isn&rsquo;t available).&nbsp; Returning 0 for samplerate or blocksize, or returning AL_NONE for format, will cause a failure.&nbsp; Returning AL_FALSE indicates failure.&nbsp; This callback is required.</td></tr><tr><td class=CDLEntry>decode</td><td class=CDLDescription>This callback is called to get more decoded data.&nbsp; Up to the specified amount of bytes should be written to the data pointer.&nbsp; The number of bytes written should be a multiple of the block size, otherwise an OpenAL error may occur during buffering.&nbsp; The function should return the number of bytes written.&nbsp; This callback is required.</td></tr><tr><td class=CDLEntry>rewind</td><td class=CDLDescription>This callback is for rewinding the instance so that the next decode calls for it will get audio data from the start of the sound file.&nbsp; If the stream fails to rewind, AL_FALSE should be returned.</td></tr><tr><td class=CDLEntry>close</td><td class=CDLDescription>This callback is called at the end of processing for a particular instance.&nbsp; The handle will not be used further and any associated data may be deleted.</td></tr></table><h4 class=CHeading>Returns</h4><p>AL_FALSE on error.</p></div></div></div>
+
+<div class="CFunction"><div class=CTopic><h3 class=CTitle><a name="alureSleep"></a>alureSleep</h3><div class=CBody><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALboolean ALURE_APIENTRY alureSleep(</td><td class=PType nowrap>ALfloat&nbsp;</td><td class=PParameter nowrap>duration</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote><p>Rests the calling thread for the given number of seconds.</p><h4 class=CHeading>Returns</h4><p>AL_FALSE on error.</p></div></div></div>
+
+<div class="CFunction"><div class=CTopic><h3 class=CTitle><a name="alureGetProcAddress"></a>alureGetProcAddress</h3><div class=CBody><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API void* ALURE_APIENTRY alureGetProcAddress(</td><td class=PTypePrefix nowrap>const&nbsp;</td><td class=PType nowrap>ALchar&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>funcname</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote><p>Returns a pointer for the named ALURE function.</p><h4 class=CHeading>Returns</h4><p>NULL on error.</p><p><b>Version Added</b>: 1.1</p></div></div></div>
+
+</div><!--Content-->
+
+
+<div id=Footer><a href="http://www.naturaldocs.org">Generated by Natural Docs</a></div><!--Footer-->
+
+
+<div id=Menu><div class=MTitle>ALURE<div class=MSubTitle>API Reference</div></div><div class=MEntry><div class=MFile id=MSelected>Main and Miscellanious</div></div><div class=MEntry><div class=MFile><a href="buffer-cpp.html">File Loading</a></div></div><div class=MEntry><div class=MFile><a href="stream-cpp.html">Streaming</a></div></div><div class=MEntry><div class=MFile><a href="istream-cpp.html">File I/<wbr>O</a></div></div><div class=MEntry><div class=MFile><a href="streamplay-cpp.html">Automatic Playback</a></div></div><div class=MEntry><div class=MGroup><a href="javascript:ToggleMenu('MGroupContent1')">Index</a><div class=MGroupContent id=MGroupContent1><div class=MEntry><div class=MIndex><a href="../index/General.html">Everything</a></div></div><div class=MEntry><div class=MIndex><a href="../index/Functions.html">Functions</a></div></div></div></div></div><script type="text/javascript"><!--
+var searchPanel = new SearchPanel("searchPanel", "HTML", "../search");
+--></script><div id=MSearchPanel class=MSearchPanelInactive><input type=text id=MSearchField value=Search onFocus="searchPanel.OnSearchFieldFocus(true)" onBlur="searchPanel.OnSearchFieldFocus(false)" onKeyUp="searchPanel.OnSearchFieldChange()"><select id=MSearchType onFocus="searchPanel.OnSearchTypeFocus(true)" onBlur="searchPanel.OnSearchTypeFocus(false)" onChange="searchPanel.OnSearchTypeChange()"><option  id=MSearchEverything selected value="General">Everything</option><option value="Functions">Functions</option></select></div></div><!--Menu-->
+
+
+
+<!--START_ND_TOOLTIPS-->
+<div class=CToolTip id="tt1"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API void ALURE_APIENTRY alureGetVersion(</td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>major,</td></tr><tr><td></td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>minor</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Stores the major and minor version of the library. </div></div><div class=CToolTip id="tt2"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API const ALchar* ALURE_APIENTRY alureGetErrorString(</td><td class=PParameter nowrap>void</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Returns a string describing the last error encountered.</div></div><div class=CToolTip id="tt3"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API const ALCchar** ALURE_APIENTRY alureGetDeviceNames(</td><td class=PType nowrap>ALCboolean&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap>all,</td></tr><tr><td></td><td class=PType nowrap>ALCsizei&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>count</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Gets an array of device name strings from OpenAL. </div></div><div class=CToolTip id="tt4"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALvoid ALURE_APIENTRY alureFreeDeviceNames(</td><td class=PTypePrefix nowrap>const&nbsp;</td><td class=PType nowrap>ALCchar&nbsp;</td><td class=PParameterPrefix nowrap>**</td><td class=PParameter nowrap>names</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Frees the device name array returned from alureGetDeviceNames.</div></div><div class=CToolTip id="tt5"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALboolean ALURE_APIENTRY alureInitDevice(</td><td class=PTypePrefix nowrap>const&nbsp;</td><td class=PType nowrap>ALCchar&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>name,</td></tr><tr><td></td><td class=PTypePrefix nowrap>const&nbsp;</td><td class=PType nowrap>ALCint&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>attribs</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Opens the named device, creates a context with the given attributes, and sets that context as current. </div></div><div class=CToolTip id="tt6"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALboolean ALURE_APIENTRY alureShutdownDevice(</td><td class=PParameter nowrap>void</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Destroys the current context and closes its associated device.</div></div><div class=CToolTip id="tt7"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALenum ALURE_APIENTRY alureGetSampleFormat(</td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameter nowrap>channels,</td></tr><tr><td></td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameter nowrap>bits,</td></tr><tr><td></td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameter nowrap>floatbits</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Retrieves an OpenAL format for the given sample format. </div></div><div class=CToolTip id="tt8"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters colspan=4>ALURE_API ALboolean ALURE_APIENTRY alureInstallDecodeCallbacks(</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALint&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>index,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>void&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>(*open_file)(const ALchar *filename),</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>void&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>(*open_memory)(const ALubyte *data, ALuint length),</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALboolean&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>(*get_format)(void *instance, ALenum *format, ALuint *samplerate, ALuint *blocksize),</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>(*decode)(void *instance, ALubyte *data, ALuint bytes),</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALboolean&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>(*rewind)(void *instance),</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>void&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>(*close)(void *instance)</td></tr><tr><td class=PAfterParameters colspan=4>)</td></tr></table></td></tr></table></blockquote>Installs callbacks to enable ALURE to handle more file types. </div></div><div class=CToolTip id="tt9"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALboolean ALURE_APIENTRY alureSleep(</td><td class=PType nowrap>ALfloat&nbsp;</td><td class=PParameter nowrap>duration</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Rests the calling thread for the given number of seconds.</div></div><div class=CToolTip id="tt10"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API void* ALURE_APIENTRY alureGetProcAddress(</td><td class=PTypePrefix nowrap>const&nbsp;</td><td class=PType nowrap>ALchar&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>funcname</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Returns a pointer for the named ALURE function.</div></div><!--END_ND_TOOLTIPS-->
+
+
+
+
+<div id=MSearchResultsWindow><iframe src="" frameborder=0 name=MSearchResults id=MSearchResults></iframe><a href="javascript:searchPanel.CloseResultsWindow()" id=MSearchResultsWindowClose>Close</a></div>
+
+
+<script language=JavaScript><!--
+if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
\ No newline at end of file
diff --git a/docs/html/files/buffer-cpp.html b/docs/html/files/buffer-cpp.html
new file mode 100644 (file)
index 0000000..33d547d
--- /dev/null
@@ -0,0 +1,48 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+
+<html><head><title>File Loading - ALURE</title><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script><script language=JavaScript src="../javascript/searchdata.js"></script></head><body class="ContentPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
+if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
+
+<!--  Generated by Natural Docs, version 1.4 -->
+<!--  http://www.naturaldocs.org  -->
+
+<!-- saved from url=(0026)http://www.naturaldocs.org -->
+
+
+
+
+<div id=Content><div class="CSection"><div class=CTopic id=MainTopic><h1 class=CTitle><a name="File_Loading"></a>File Loading</h1><div class=CBody><!--START_ND_SUMMARY--><div class=Summary><div class=STitle>Summary</div><div class=SBorder><table border=0 cellspacing=0 cellpadding=0 class=STable><tr class="SMain"><td class=SEntry><a href="#File_Loading" >File Loading</a></td><td class=SDescription></td></tr><tr class="SGroup SIndent1"><td class=SEntry><a href="#Functions" >Functions</a></td><td class=SDescription></td></tr><tr class="SFunction SIndent2 SMarked"><td class=SEntry><a href="#alureCreateBufferFromFile" id=link1 onMouseOver="ShowTip(event, 'tt1', 'link1')" onMouseOut="HideTip('tt1')">alureCreateBufferFromFile</a></td><td class=SDescription>Loads the given file into a new OpenAL buffer object. </td></tr><tr class="SFunction SIndent2"><td class=SEntry><a href="#alureCreateBufferFromMemory" id=link2 onMouseOver="ShowTip(event, 'tt2', 'link2')" onMouseOut="HideTip('tt2')">alureCreateBufferFromMemory</a></td><td class=SDescription>Loads a file image from memory into a new OpenAL buffer object, similar to alureCreateBufferFromFile. </td></tr><tr class="SFunction SIndent2 SMarked"><td class=SEntry><a href="#alureBufferDataFromFile" id=link3 onMouseOver="ShowTip(event, 'tt3', 'link3')" onMouseOut="HideTip('tt3')">alureBufferDataFromFile</a></td><td class=SDescription>Loads the given file into an existing OpenAL buffer object. </td></tr><tr class="SFunction SIndent2"><td class=SEntry><a href="#alureBufferDataFromMemory" id=link4 onMouseOver="ShowTip(event, 'tt4', 'link4')" onMouseOut="HideTip('tt4')">alureBufferDataFromMemory</a></td><td class=SDescription>Loads a file image from memory into an existing OpenAL buffer object, similar to alureBufferDataFromFile. </td></tr></table></div></div><!--END_ND_SUMMARY--></div></div></div>
+
+<div class="CGroup"><div class=CTopic><h3 class=CTitle><a name="Functions"></a>Functions</h3></div></div>
+
+<div class="CFunction"><div class=CTopic><h3 class=CTitle><a name="alureCreateBufferFromFile"></a>alureCreateBufferFromFile</h3><div class=CBody><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALuint ALURE_APIENTRY alureCreateBufferFromFile(</td><td class=PTypePrefix nowrap>const&nbsp;</td><td class=PType nowrap>ALchar&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>fname</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote><p>Loads the given file into a new OpenAL buffer object.&nbsp; The formats supported depend on the options the library was compiled with, what libraries are available at runtime, and the installed decode callbacks.&nbsp; Requires an active context.</p><h4 class=CHeading>Returns</h4><p>A new buffer ID with the loaded sound, or AL_NONE on error.</p><h4 class=CHeading>See Also</h4><p><a href="#alureBufferDataFromFile" class=LFunction id=link5 onMouseOver="ShowTip(event, 'tt3', 'link5')" onMouseOut="HideTip('tt3')">alureBufferDataFromFile</a></p></div></div></div>
+
+<div class="CFunction"><div class=CTopic><h3 class=CTitle><a name="alureCreateBufferFromMemory"></a>alureCreateBufferFromMemory</h3><div class=CBody><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters colspan=5>ALURE_API ALuint ALURE_APIENTRY alureCreateBufferFromMemory(</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap>const&nbsp;</td><td class=PType nowrap>ALubyte&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>fdata,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>length</td></tr><tr><td class=PAfterParameters colspan=5>)</td></tr></table></td></tr></table></blockquote><p>Loads a file image from memory into a new OpenAL buffer object, similar to alureCreateBufferFromFile.&nbsp; Requires an active context.</p><h4 class=CHeading>Returns</h4><p>A new buffer ID with the loaded sound, or AL_NONE on error.</p><h4 class=CHeading>See Also</h4><p><a href="#alureBufferDataFromMemory" class=LFunction id=link6 onMouseOver="ShowTip(event, 'tt4', 'link6')" onMouseOut="HideTip('tt4')">alureBufferDataFromMemory</a></p></div></div></div>
+
+<div class="CFunction"><div class=CTopic><h3 class=CTitle><a name="alureBufferDataFromFile"></a>alureBufferDataFromFile</h3><div class=CBody><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters colspan=5>ALURE_API ALboolean ALURE_APIENTRY alureBufferDataFromFile(</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap>const&nbsp;</td><td class=PType nowrap>ALchar&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>fname,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>buffer</td></tr><tr><td class=PAfterParameters colspan=5>)</td></tr></table></td></tr></table></blockquote><p>Loads the given file into an existing OpenAL buffer object.&nbsp; The previous contents of the buffer are replaced.&nbsp; Requires an active context.</p><h4 class=CHeading>Returns</h4><p>AL_FALSE on error.</p><h4 class=CHeading>See Also</h4><p><a href="#alureCreateBufferFromFile" class=LFunction id=link7 onMouseOver="ShowTip(event, 'tt1', 'link7')" onMouseOut="HideTip('tt1')">alureCreateBufferFromFile</a></p></div></div></div>
+
+<div class="CFunction"><div class=CTopic><h3 class=CTitle><a name="alureBufferDataFromMemory"></a>alureBufferDataFromMemory</h3><div class=CBody><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters colspan=5>ALURE_API ALboolean ALURE_APIENTRY alureBufferDataFromMemory(</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap>const&nbsp;</td><td class=PType nowrap>ALubyte&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>fdata,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>length,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>buffer</td></tr><tr><td class=PAfterParameters colspan=5>)</td></tr></table></td></tr></table></blockquote><p>Loads a file image from memory into an existing OpenAL buffer object, similar to alureBufferDataFromFile.&nbsp; Requires an active context.</p><h4 class=CHeading>Returns</h4><p>AL_FALSE on error.</p><h4 class=CHeading>See Also</h4><p><a href="#alureCreateBufferFromMemory" class=LFunction id=link8 onMouseOver="ShowTip(event, 'tt2', 'link8')" onMouseOut="HideTip('tt2')">alureCreateBufferFromMemory</a></p></div></div></div>
+
+</div><!--Content-->
+
+
+<div id=Footer><a href="http://www.naturaldocs.org">Generated by Natural Docs</a></div><!--Footer-->
+
+
+<div id=Menu><div class=MTitle>ALURE<div class=MSubTitle>API Reference</div></div><div class=MEntry><div class=MFile><a href="alure-cpp.html">Main and Miscellanious</a></div></div><div class=MEntry><div class=MFile id=MSelected>File Loading</div></div><div class=MEntry><div class=MFile><a href="stream-cpp.html">Streaming</a></div></div><div class=MEntry><div class=MFile><a href="istream-cpp.html">File I/<wbr>O</a></div></div><div class=MEntry><div class=MFile><a href="streamplay-cpp.html">Automatic Playback</a></div></div><div class=MEntry><div class=MGroup><a href="javascript:ToggleMenu('MGroupContent1')">Index</a><div class=MGroupContent id=MGroupContent1><div class=MEntry><div class=MIndex><a href="../index/General.html">Everything</a></div></div><div class=MEntry><div class=MIndex><a href="../index/Functions.html">Functions</a></div></div></div></div></div><script type="text/javascript"><!--
+var searchPanel = new SearchPanel("searchPanel", "HTML", "../search");
+--></script><div id=MSearchPanel class=MSearchPanelInactive><input type=text id=MSearchField value=Search onFocus="searchPanel.OnSearchFieldFocus(true)" onBlur="searchPanel.OnSearchFieldFocus(false)" onKeyUp="searchPanel.OnSearchFieldChange()"><select id=MSearchType onFocus="searchPanel.OnSearchTypeFocus(true)" onBlur="searchPanel.OnSearchTypeFocus(false)" onChange="searchPanel.OnSearchTypeChange()"><option  id=MSearchEverything selected value="General">Everything</option><option value="Functions">Functions</option></select></div></div><!--Menu-->
+
+
+
+<!--START_ND_TOOLTIPS-->
+<div class=CToolTip id="tt1"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALuint ALURE_APIENTRY alureCreateBufferFromFile(</td><td class=PTypePrefix nowrap>const&nbsp;</td><td class=PType nowrap>ALchar&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>fname</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Loads the given file into a new OpenAL buffer object. </div></div><div class=CToolTip id="tt2"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters colspan=5>ALURE_API ALuint ALURE_APIENTRY alureCreateBufferFromMemory(</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap>const&nbsp;</td><td class=PType nowrap>ALubyte&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>fdata,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>length</td></tr><tr><td class=PAfterParameters colspan=5>)</td></tr></table></td></tr></table></blockquote>Loads a file image from memory into a new OpenAL buffer object, similar to alureCreateBufferFromFile. </div></div><div class=CToolTip id="tt3"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters colspan=5>ALURE_API ALboolean ALURE_APIENTRY alureBufferDataFromFile(</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap>const&nbsp;</td><td class=PType nowrap>ALchar&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>fname,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>buffer</td></tr><tr><td class=PAfterParameters colspan=5>)</td></tr></table></td></tr></table></blockquote>Loads the given file into an existing OpenAL buffer object. </div></div><div class=CToolTip id="tt4"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters colspan=5>ALURE_API ALboolean ALURE_APIENTRY alureBufferDataFromMemory(</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap>const&nbsp;</td><td class=PType nowrap>ALubyte&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>fdata,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>length,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>buffer</td></tr><tr><td class=PAfterParameters colspan=5>)</td></tr></table></td></tr></table></blockquote>Loads a file image from memory into an existing OpenAL buffer object, similar to alureBufferDataFromFile. </div></div><!--END_ND_TOOLTIPS-->
+
+
+
+
+<div id=MSearchResultsWindow><iframe src="" frameborder=0 name=MSearchResults id=MSearchResults></iframe><a href="javascript:searchPanel.CloseResultsWindow()" id=MSearchResultsWindowClose>Close</a></div>
+
+
+<script language=JavaScript><!--
+if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
\ No newline at end of file
diff --git a/docs/html/files/istream-cpp.html b/docs/html/files/istream-cpp.html
new file mode 100644 (file)
index 0000000..99d891e
--- /dev/null
@@ -0,0 +1,42 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+
+<html><head><title>File I/O - ALURE</title><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script><script language=JavaScript src="../javascript/searchdata.js"></script></head><body class="ContentPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
+if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
+
+<!--  Generated by Natural Docs, version 1.4 -->
+<!--  http://www.naturaldocs.org  -->
+
+<!-- saved from url=(0026)http://www.naturaldocs.org -->
+
+
+
+
+<div id=Content><div class="CSection"><div class=CTopic id=MainTopic><h1 class=CTitle><a name="File_I/O"></a>File I/<wbr>O</h1><div class=CBody><!--START_ND_SUMMARY--><div class=Summary><div class=STitle>Summary</div><div class=SBorder><table border=0 cellspacing=0 cellpadding=0 class=STable><tr class="SMain"><td class=SEntry><a href="#File_I/O" >File I/<wbr>O</a></td><td class=SDescription></td></tr><tr class="SGroup SIndent1"><td class=SEntry><a href="#Functions" >Functions</a></td><td class=SDescription></td></tr><tr class="SFunction SIndent2 SMarked"><td class=SEntry><a href="#alureSetIOCallbacks" id=link1 onMouseOver="ShowTip(event, 'tt1', 'link1')" onMouseOut="HideTip('tt1')">alureSetIOCallbacks</a></td><td class=SDescription>Provides callbacks for alternative methods to handle file I/O. </td></tr></table></div></div><!--END_ND_SUMMARY--></div></div></div>
+
+<div class="CGroup"><div class=CTopic><h3 class=CTitle><a name="Functions"></a>Functions</h3></div></div>
+
+<div class="CFunction"><div class=CTopic><h3 class=CTitle><a name="alureSetIOCallbacks"></a>alureSetIOCallbacks</h3><div class=CBody><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters colspan=4>ALURE_API ALboolean ALURE_APIENTRY alureSetIOCallbacks(</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>void&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>(*open)(const char *filename, ALuint mode),</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>void&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>(*close)(void *handle),</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>(*read)(void *handle, ALubyte *buf, ALuint bytes),</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>(*write)(void *handle, const ALubyte *buf, ALuint bytes),</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>alureInt64&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>(*seek)(void *handle, alureInt64 offset, int whence)</td></tr><tr><td class=PAfterParameters colspan=4>)</td></tr></table></td></tr></table></blockquote><p>Provides callbacks for alternative methods to handle file I/O.&nbsp; Passing NULL for all callbacks is a valid way to revert to normal I/O, otherwise they must all be specified.&nbsp; Changing the callbacks will not affect open files (they will continue using the callbacks that were set at the time they were opened).</p><h4 class=CHeading>Parameters</h4><table border=0 cellspacing=0 cellpadding=0 class=CDescriptionList><tr><td class=CDLEntry>open</td><td class=CDLDescription>This callback is called to open the named file.&nbsp; The given mode is the access rights the open file should have.&nbsp; Currently, this will always be 0 for read-only (applications should check this to make sure, as future versions may pass other values for other modes).&nbsp; Upon success, a non-NULL handle must be returned which will be used as a unique identifier for the file.</td></tr><tr><td class=CDLEntry>close</td><td class=CDLDescription>This callback is called to close an opened file handle.&nbsp; The handle will no longer be used after this function.</td></tr><tr><td class=CDLEntry>read</td><td class=CDLDescription>This callback is called when data needs to be read from the given handle.&nbsp; Up to the given number of bytes should be copied into &lsquo;buf&rsquo; and the number of bytes actually copied should be returned.&nbsp; Returning 0 means the end of the file has been reached (so non-blocking I/O methods should ensure at least 1 byte gets read), and negative indicates an error.</td></tr><tr><td class=CDLEntry>write</td><td class=CDLDescription>This callback is called when data needs to be written to the given handle.&nbsp; Up to the given number of bytes should be copied from &lsquo;buf&rsquo; and the number of bytes actually copied should be returned.&nbsp; A return value of 0 means no more data can be written (so non-blocking I/O methods should ensure at least 1 byte gets written), and negative indicates an error.</td></tr><tr><td class=CDLEntry>seek</td><td class=CDLDescription>This callback is called to reposition the offset of the file handle.&nbsp; The given offset is interpreted according to &lsquo;whence&rsquo;, which may be SEEK_SET (absolute position from the start of the file), SEEK_CUR (relative position from the current offset), or SEEK_END (absolute position from the end of the file), as defined by standard C.&nbsp; The new offset from the beginning of the file should be returned.&nbsp; If the file cannot seek, such as when using a FIFO, -1 should be returned.</td></tr></table><h4 class=CHeading>Returns</h4><p>AL_FALSE on error.</p><p><b>Version Added</b>: 1.1</p></div></div></div>
+
+</div><!--Content-->
+
+
+<div id=Footer><a href="http://www.naturaldocs.org">Generated by Natural Docs</a></div><!--Footer-->
+
+
+<div id=Menu><div class=MTitle>ALURE<div class=MSubTitle>API Reference</div></div><div class=MEntry><div class=MFile><a href="alure-cpp.html">Main and Miscellanious</a></div></div><div class=MEntry><div class=MFile><a href="buffer-cpp.html">File Loading</a></div></div><div class=MEntry><div class=MFile><a href="stream-cpp.html">Streaming</a></div></div><div class=MEntry><div class=MFile id=MSelected>File I/<wbr>O</div></div><div class=MEntry><div class=MFile><a href="streamplay-cpp.html">Automatic Playback</a></div></div><div class=MEntry><div class=MGroup><a href="javascript:ToggleMenu('MGroupContent1')">Index</a><div class=MGroupContent id=MGroupContent1><div class=MEntry><div class=MIndex><a href="../index/General.html">Everything</a></div></div><div class=MEntry><div class=MIndex><a href="../index/Functions.html">Functions</a></div></div></div></div></div><script type="text/javascript"><!--
+var searchPanel = new SearchPanel("searchPanel", "HTML", "../search");
+--></script><div id=MSearchPanel class=MSearchPanelInactive><input type=text id=MSearchField value=Search onFocus="searchPanel.OnSearchFieldFocus(true)" onBlur="searchPanel.OnSearchFieldFocus(false)" onKeyUp="searchPanel.OnSearchFieldChange()"><select id=MSearchType onFocus="searchPanel.OnSearchTypeFocus(true)" onBlur="searchPanel.OnSearchTypeFocus(false)" onChange="searchPanel.OnSearchTypeChange()"><option  id=MSearchEverything selected value="General">Everything</option><option value="Functions">Functions</option></select></div></div><!--Menu-->
+
+
+
+<!--START_ND_TOOLTIPS-->
+<div class=CToolTip id="tt1"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters colspan=4>ALURE_API ALboolean ALURE_APIENTRY alureSetIOCallbacks(</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>void&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>(*open)(const char *filename, ALuint mode),</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>void&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>(*close)(void *handle),</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>(*read)(void *handle, ALubyte *buf, ALuint bytes),</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>(*write)(void *handle, const ALubyte *buf, ALuint bytes),</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>alureInt64&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>(*seek)(void *handle, alureInt64 offset, int whence)</td></tr><tr><td class=PAfterParameters colspan=4>)</td></tr></table></td></tr></table></blockquote>Provides callbacks for alternative methods to handle file I/O. </div></div><!--END_ND_TOOLTIPS-->
+
+
+
+
+<div id=MSearchResultsWindow><iframe src="" frameborder=0 name=MSearchResults id=MSearchResults></iframe><a href="javascript:searchPanel.CloseResultsWindow()" id=MSearchResultsWindowClose>Close</a></div>
+
+
+<script language=JavaScript><!--
+if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
\ No newline at end of file
diff --git a/docs/html/files/stream-cpp.html b/docs/html/files/stream-cpp.html
new file mode 100644 (file)
index 0000000..1af4a81
--- /dev/null
@@ -0,0 +1,64 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+
+<html><head><title>Streaming - ALURE</title><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script><script language=JavaScript src="../javascript/searchdata.js"></script></head><body class="ContentPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
+if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
+
+<!--  Generated by Natural Docs, version 1.4 -->
+<!--  http://www.naturaldocs.org  -->
+
+<!-- saved from url=(0026)http://www.naturaldocs.org -->
+
+
+
+
+<div id=Content><div class="CSection"><div class=CTopic id=MainTopic><h1 class=CTitle><a name="Streaming"></a>Streaming</h1><div class=CBody><!--START_ND_SUMMARY--><div class=Summary><div class=STitle>Summary</div><div class=SBorder><table border=0 cellspacing=0 cellpadding=0 class=STable><tr class="SMain"><td class=SEntry><a href="#Streaming" >Streaming</a></td><td class=SDescription></td></tr><tr class="SGroup SIndent1"><td class=SEntry><a href="#Functions" >Functions</a></td><td class=SDescription></td></tr><tr class="SFunction SIndent2 SMarked"><td class=SEntry><a href="#alureStreamSizeIsMicroSec" id=link1 onMouseOver="ShowTip(event, 'tt1', 'link1')" onMouseOut="HideTip('tt1')">alureStreamSizeIsMicroSec</a></td><td class=SDescription>Specifies if the chunk size value given to the alureCreateStream functions is in bytes (default) or microseconds. </td></tr><tr class="SFunction SIndent2"><td class=SEntry><a href="#alureCreateStreamFromFile" id=link2 onMouseOver="ShowTip(event, 'tt2', 'link2')" onMouseOut="HideTip('tt2')">alureCreateStreamFromFile</a></td><td class=SDescription>Opens a file and sets it up for streaming. </td></tr><tr class="SFunction SIndent2 SMarked"><td class=SEntry><a href="#alureCreateStreamFromMemory" id=link3 onMouseOver="ShowTip(event, 'tt3', 'link3')" onMouseOut="HideTip('tt3')">alureCreateStreamFromMemory</a></td><td class=SDescription>Opens a file image from memory and sets it up for streaming, similar to <a href="#alureCreateStreamFromFile" class=LFunction id=link4 onMouseOver="ShowTip(event, 'tt2', 'link4')" onMouseOut="HideTip('tt2')">alureCreateStreamFromFile</a>. </td></tr><tr class="SFunction SIndent2"><td class=SEntry><a href="#alureCreateStreamFromStaticMemory" id=link5 onMouseOver="ShowTip(event, 'tt4', 'link5')" onMouseOut="HideTip('tt4')">alureCreateStreamFromStaticMemory</a></td><td class=SDescription>Identical to <a href="#alureCreateStreamFromMemory" class=LFunction id=link6 onMouseOver="ShowTip(event, 'tt3', 'link6')" onMouseOut="HideTip('tt3')">alureCreateStreamFromMemory</a>, except the given memory is used directly and not duplicated. </td></tr><tr class="SFunction SIndent2 SMarked"><td class=SEntry><a href="#alureCreateStreamFromCallback" id=link7 onMouseOver="ShowTip(event, 'tt5', 'link7')" onMouseOut="HideTip('tt5')">alureCreateStreamFromCallback</a></td><td class=SDescription>Creates a stream using the specified callback to retrieve data. </td></tr><tr class="SFunction SIndent2"><td class=SEntry><a href="#alureGetStreamFrequency" id=link8 onMouseOver="ShowTip(event, 'tt6', 'link8')" onMouseOut="HideTip('tt6')">alureGetStreamFrequency</a></td><td class=SDescription>Retrieves the frequency used by the given stream.</td></tr><tr class="SFunction SIndent2 SMarked"><td class=SEntry><a href="#alureBufferDataFromStream" id=link9 onMouseOver="ShowTip(event, 'tt7', 'link9')" onMouseOut="HideTip('tt7')">alureBufferDataFromStream</a></td><td class=SDescription>Buffers the given buffer objects with the next chunks of data from the stream. </td></tr><tr class="SFunction SIndent2"><td class=SEntry><a href="#alureRewindStream" id=link10 onMouseOver="ShowTip(event, 'tt8', 'link10')" onMouseOut="HideTip('tt8')">alureRewindStream</a></td><td class=SDescription>Rewinds the stream so that the next alureBufferDataFromStream call will restart from the beginning of the audio file.</td></tr><tr class="SFunction SIndent2 SMarked"><td class=SEntry><a href="#alureSetStreamOrder" id=link11 onMouseOver="ShowTip(event, 'tt9', 'link11')" onMouseOut="HideTip('tt9')">alureSetStreamOrder</a></td><td class=SDescription>Skips the module decoder to the specified order, so following buffering calls will decode from the specified order. </td></tr><tr class="SFunction SIndent2"><td class=SEntry><a href="#alureSetStreamPatchset" id=link12 onMouseOver="ShowTip(event, 'tt10', 'link12')" onMouseOut="HideTip('tt10')">alureSetStreamPatchset</a></td><td class=SDescription>Specifies the patchset to use for MIDI streams. </td></tr><tr class="SFunction SIndent2 SMarked"><td class=SEntry><a href="#alureGetStreamLength" id=link13 onMouseOver="ShowTip(event, 'tt11', 'link13')" onMouseOut="HideTip('tt11')">alureGetStreamLength</a></td><td class=SDescription>Retrieves an approximate number of samples for the stream. </td></tr><tr class="SFunction SIndent2"><td class=SEntry><a href="#alureDestroyStream" id=link14 onMouseOver="ShowTip(event, 'tt12', 'link14')" onMouseOut="HideTip('tt12')">alureDestroyStream</a></td><td class=SDescription>Closes an opened stream. </td></tr></table></div></div><!--END_ND_SUMMARY--></div></div></div>
+
+<div class="CGroup"><div class=CTopic><h3 class=CTitle><a name="Functions"></a>Functions</h3></div></div>
+
+<div class="CFunction"><div class=CTopic><h3 class=CTitle><a name="alureStreamSizeIsMicroSec"></a>alureStreamSizeIsMicroSec</h3><div class=CBody><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALboolean ALURE_APIENTRY alureStreamSizeIsMicroSec(</td><td class=PType nowrap>ALboolean&nbsp;</td><td class=PParameter nowrap>useUS</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote><p>Specifies if the chunk size value given to the alureCreateStream functions is in bytes (default) or microseconds.&nbsp; Specifying the size in microseconds can help manage the time needed in between needed updates (since the format and sample rate of the stream may not be known), while specifying the size in bytes can help control memory usage.</p><h4 class=CHeading>Returns</h4><p>Previously set value.</p><p><b>Version Added</b>: 1.1</p><h4 class=CHeading>See Also</h4><p><a href="#alureCreateStreamFromFile" class=LFunction id=link15 onMouseOver="ShowTip(event, 'tt2', 'link15')" onMouseOut="HideTip('tt2')">alureCreateStreamFromFile</a>, <a href="#alureCreateStreamFromMemory" class=LFunction id=link16 onMouseOver="ShowTip(event, 'tt3', 'link16')" onMouseOut="HideTip('tt3')">alureCreateStreamFromMemory</a>, <a href="#alureCreateStreamFromStaticMemory" class=LFunction id=link17 onMouseOver="ShowTip(event, 'tt4', 'link17')" onMouseOut="HideTip('tt4')">alureCreateStreamFromStaticMemory</a>, <a href="#alureCreateStreamFromCallback" class=LFunction id=link18 onMouseOver="ShowTip(event, 'tt5', 'link18')" onMouseOut="HideTip('tt5')">alureCreateStreamFromCallback</a></p></div></div></div>
+
+<div class="CFunction"><div class=CTopic><h3 class=CTitle><a name="alureCreateStreamFromFile"></a>alureCreateStreamFromFile</h3><div class=CBody><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters colspan=5>ALURE_API alureStream* ALURE_APIENTRY alureCreateStreamFromFile(</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap>const&nbsp;</td><td class=PType nowrap>ALchar&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>fname,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>chunkLength,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>numBufs,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>bufs</td></tr><tr><td class=PAfterParameters colspan=5>)</td></tr></table></td></tr></table></blockquote><p>Opens a file and sets it up for streaming.&nbsp; The given chunkLength is the number of bytes, or microseconds worth of bytes if <a href="#alureStreamSizeIsMicroSec" class=LFunction id=link19 onMouseOver="ShowTip(event, 'tt1', 'link19')" onMouseOut="HideTip('tt1')">alureStreamSizeIsMicroSec</a> was last called with AL_TRUE, each buffer will fill with.&nbsp; ALURE will optionally generate the specified number of buffer objects, fill them with the beginning of the data, then place the new IDs into the provided storage, before returning.&nbsp; Requires an active context.</p><h4 class=CHeading>Returns</h4><p>An opaque handle used to control the opened stream, or NULL on error.</p><h4 class=CHeading>See Also</h4><p><a href="#alureStreamSizeIsMicroSec" class=LFunction id=link20 onMouseOver="ShowTip(event, 'tt1', 'link20')" onMouseOut="HideTip('tt1')">alureStreamSizeIsMicroSec</a>, <a href="#alureCreateStreamFromMemory" class=LFunction id=link21 onMouseOver="ShowTip(event, 'tt3', 'link21')" onMouseOut="HideTip('tt3')">alureCreateStreamFromMemory</a>, <a href="#alureCreateStreamFromStaticMemory" class=LFunction id=link22 onMouseOver="ShowTip(event, 'tt4', 'link22')" onMouseOut="HideTip('tt4')">alureCreateStreamFromStaticMemory</a>, <a href="#alureCreateStreamFromCallback" class=LFunction id=link23 onMouseOver="ShowTip(event, 'tt5', 'link23')" onMouseOut="HideTip('tt5')">alureCreateStreamFromCallback</a></p></div></div></div>
+
+<div class="CFunction"><div class=CTopic><h3 class=CTitle><a name="alureCreateStreamFromMemory"></a>alureCreateStreamFromMemory</h3><div class=CBody><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters colspan=5>ALURE_API alureStream* ALURE_APIENTRY alureCreateStreamFromMemory(</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap>const&nbsp;</td><td class=PType nowrap>ALubyte&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>fdata,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>length,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>chunkLength,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>numBufs,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>bufs</td></tr><tr><td class=PAfterParameters colspan=5>)</td></tr></table></td></tr></table></blockquote><p>Opens a file image from memory and sets it up for streaming, similar to <a href="#alureCreateStreamFromFile" class=LFunction id=link24 onMouseOver="ShowTip(event, 'tt2', 'link24')" onMouseOut="HideTip('tt2')">alureCreateStreamFromFile</a>.&nbsp; The given data buffer can be safely deleted after calling this function.&nbsp; Requires an active context.</p><h4 class=CHeading>Returns</h4><p>An opaque handle used to control the opened stream, or NULL on error.</p><h4 class=CHeading>See Also</h4><p><a href="#alureStreamSizeIsMicroSec" class=LFunction id=link25 onMouseOver="ShowTip(event, 'tt1', 'link25')" onMouseOut="HideTip('tt1')">alureStreamSizeIsMicroSec</a>, <a href="#alureCreateStreamFromFile" class=LFunction id=link26 onMouseOver="ShowTip(event, 'tt2', 'link26')" onMouseOut="HideTip('tt2')">alureCreateStreamFromFile</a>, <a href="#alureCreateStreamFromStaticMemory" class=LFunction id=link27 onMouseOver="ShowTip(event, 'tt4', 'link27')" onMouseOut="HideTip('tt4')">alureCreateStreamFromStaticMemory</a>, <a href="#alureCreateStreamFromCallback" class=LFunction id=link28 onMouseOver="ShowTip(event, 'tt5', 'link28')" onMouseOut="HideTip('tt5')">alureCreateStreamFromCallback</a></p></div></div></div>
+
+<div class="CFunction"><div class=CTopic><h3 class=CTitle><a name="alureCreateStreamFromStaticMemory"></a>alureCreateStreamFromStaticMemory</h3><div class=CBody><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters colspan=5>ALURE_API alureStream* ALURE_APIENTRY alureCreateStreamFromStaticMemory(</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap>const&nbsp;</td><td class=PType nowrap>ALubyte&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>fdata,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>length,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>chunkLength,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>numBufs,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>bufs</td></tr><tr><td class=PAfterParameters colspan=5>)</td></tr></table></td></tr></table></blockquote><p>Identical to <a href="#alureCreateStreamFromMemory" class=LFunction id=link29 onMouseOver="ShowTip(event, 'tt3', 'link29')" onMouseOut="HideTip('tt3')">alureCreateStreamFromMemory</a>, except the given memory is used directly and not duplicated.&nbsp; As a consequence, the data buffer must remain valid while the stream is alive.&nbsp; Requires an active context.</p><h4 class=CHeading>Returns</h4><p>An opaque handle used to control the opened stream, or NULL on error.</p><h4 class=CHeading>See Also</h4><p><a href="#alureStreamSizeIsMicroSec" class=LFunction id=link30 onMouseOver="ShowTip(event, 'tt1', 'link30')" onMouseOut="HideTip('tt1')">alureStreamSizeIsMicroSec</a>, <a href="#alureCreateStreamFromFile" class=LFunction id=link31 onMouseOver="ShowTip(event, 'tt2', 'link31')" onMouseOut="HideTip('tt2')">alureCreateStreamFromFile</a>, <a href="#alureCreateStreamFromMemory" class=LFunction id=link32 onMouseOver="ShowTip(event, 'tt3', 'link32')" onMouseOut="HideTip('tt3')">alureCreateStreamFromMemory</a>, <a href="#alureCreateStreamFromCallback" class=LFunction id=link33 onMouseOver="ShowTip(event, 'tt5', 'link33')" onMouseOut="HideTip('tt5')">alureCreateStreamFromCallback</a></p></div></div></div>
+
+<div class="CFunction"><div class=CTopic><h3 class=CTitle><a name="alureCreateStreamFromCallback"></a>alureCreateStreamFromCallback</h3><div class=CBody><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters colspan=4>ALURE_API alureStream* ALURE_APIENTRY alureCreateStreamFromCallback(</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>(*callback)(void *userdata, ALubyte *data, ALuint bytes),</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>void&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>userdata,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALenum&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>format,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>samplerate,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>chunkLength,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>numBufs,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>bufs</td></tr><tr><td class=PAfterParameters colspan=4>)</td></tr></table></td></tr></table></blockquote><p>Creates a stream using the specified callback to retrieve data.&nbsp; Requires an active context.</p><h4 class=CHeading>Parameters</h4><table border=0 cellspacing=0 cellpadding=0 class=CDescriptionList><tr><td class=CDLEntry>callback</td><td class=CDLDescription>This is called when more data is needed from the stream.&nbsp; Up to the specified number of bytes should be written to the data pointer, and the number of bytes actually written should be returned.&nbsp; The number of bytes written must be block aligned for the format (eg. a multiple of 4 for AL_FORMAT_STEREO16), or an OpenAL error may occur during buffering.</td></tr><tr><td class=CDLEntry>userdata</td><td class=CDLDescription>A handle passed through to the callback.</td></tr><tr><td class=CDLEntry>format</td><td class=CDLDescription>The format of the data the callback will be giving.&nbsp; The format must be valid for the context.</td></tr><tr><td class=CDLEntry>samplerate</td><td class=CDLDescription>The sample rate (frequency) of the stream</td></tr></table><h4 class=CHeading>Returns</h4><p>An opaque handle used to control the opened stream, or NULL on error.</p><h4 class=CHeading>See Also</h4><p><a href="#alureStreamSizeIsMicroSec" class=LFunction id=link34 onMouseOver="ShowTip(event, 'tt1', 'link34')" onMouseOut="HideTip('tt1')">alureStreamSizeIsMicroSec</a>, <a href="#alureCreateStreamFromFile" class=LFunction id=link35 onMouseOver="ShowTip(event, 'tt2', 'link35')" onMouseOut="HideTip('tt2')">alureCreateStreamFromFile</a>, <a href="#alureCreateStreamFromMemory" class=LFunction id=link36 onMouseOver="ShowTip(event, 'tt3', 'link36')" onMouseOut="HideTip('tt3')">alureCreateStreamFromMemory</a>, <a href="#alureCreateStreamFromStaticMemory" class=LFunction id=link37 onMouseOver="ShowTip(event, 'tt4', 'link37')" onMouseOut="HideTip('tt4')">alureCreateStreamFromStaticMemory</a></p></div></div></div>
+
+<div class="CFunction"><div class=CTopic><h3 class=CTitle><a name="alureGetStreamFrequency"></a>alureGetStreamFrequency</h3><div class=CBody><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALsizei ALURE_APIENTRY alureGetStreamFrequency(</td><td class=PType nowrap>alureStream&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>stream</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote><p>Retrieves the frequency used by the given stream.</p><h4 class=CHeading>Returns</h4><p>0 on error.</p><p><b>Version Added</b>: 1.1</p></div></div></div>
+
+<div class="CFunction"><div class=CTopic><h3 class=CTitle><a name="alureBufferDataFromStream"></a>alureBufferDataFromStream</h3><div class=CBody><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALsizei ALURE_APIENTRY alureBufferDataFromStream(</td><td class=PType nowrap>alureStream&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>stream,</td></tr><tr><td></td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap>numBufs,</td></tr><tr><td></td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>bufs</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote><p>Buffers the given buffer objects with the next chunks of data from the stream.&nbsp; The given buffer objects do not need to be ones given by the alureCreateStream functions.&nbsp; Requires an active context.</p><h4 class=CHeading>Returns</h4><p>The number of buffers filled with new data, or -1 on error.&nbsp; If the value returned is less than the number requested, the end of the stream has been reached.</p></div></div></div>
+
+<div class="CFunction"><div class=CTopic><h3 class=CTitle><a name="alureRewindStream"></a>alureRewindStream</h3><div class=CBody><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALboolean ALURE_APIENTRY alureRewindStream(</td><td class=PType nowrap>alureStream&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>stream</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote><p>Rewinds the stream so that the next alureBufferDataFromStream call will restart from the beginning of the audio file.</p><h4 class=CHeading>Returns</h4><p>AL_FALSE on error.</p><h4 class=CHeading>See Also</h4><p><a href="#alureSetStreamOrder" class=LFunction id=link38 onMouseOver="ShowTip(event, 'tt9', 'link38')" onMouseOut="HideTip('tt9')">alureSetStreamOrder</a></p></div></div></div>
+
+<div class="CFunction"><div class=CTopic><h3 class=CTitle><a name="alureSetStreamOrder"></a>alureSetStreamOrder</h3><div class=CBody><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALboolean ALURE_APIENTRY alureSetStreamOrder(</td><td class=PType nowrap>alureStream&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>stream,</td></tr><tr><td></td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap>order</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote><p>Skips the module decoder to the specified order, so following buffering calls will decode from the specified order.&nbsp; For non-module formats, setting order 0 is identical to rewinding the stream (other orders will fail).</p><h4 class=CHeading>Returns</h4><p>AL_FALSE on error.</p><p><b>Version Added</b>: 1.1</p><h4 class=CHeading>See Also</h4><p><a href="#alureRewindStream" class=LFunction id=link39 onMouseOver="ShowTip(event, 'tt8', 'link39')" onMouseOut="HideTip('tt8')">alureRewindStream</a></p></div></div></div>
+
+<div class="CFunction"><div class=CTopic><h3 class=CTitle><a name="alureSetStreamPatchset"></a>alureSetStreamPatchset</h3><div class=CBody><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters colspan=5>ALURE_API ALboolean ALURE_APIENTRY alureSetStreamPatchset(</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>alureStream&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>stream,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap>const&nbsp;</td><td class=PType nowrap>ALchar&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>patchset</td></tr><tr><td class=PAfterParameters colspan=5>)</td></tr></table></td></tr></table></blockquote><p>Specifies the patchset to use for MIDI streams.&nbsp; By default, the FluidSynth decoder will look for one in the FLUID_SOUNDFONT environment variable, but this can be used to change it to something different.&nbsp; On non-MIDI streams, this has no effect.</p><h4 class=CHeading>Returns</h4><p>AL_FALSE on error.</p><p><b>Version Added</b>: 1.1</p></div></div></div>
+
+<div class="CFunction"><div class=CTopic><h3 class=CTitle><a name="alureGetStreamLength"></a>alureGetStreamLength</h3><div class=CBody><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API alureInt64 ALURE_APIENTRY alureGetStreamLength(</td><td class=PType nowrap>alureStream&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>stream</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote><p>Retrieves an approximate number of samples for the stream.&nbsp; Not all streams or decoders can return such info, and may return 0 if the stream length is unknown.</p><h4 class=CHeading>Returns</h4><p>-1 on error.</p><p><b>Version Added</b>: 1.2</p></div></div></div>
+
+<div class="CFunction"><div class=CTopic><h3 class=CTitle><a name="alureDestroyStream"></a>alureDestroyStream</h3><div class=CBody><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALboolean ALURE_APIENTRY alureDestroyStream(</td><td class=PType nowrap>alureStream&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>stream,</td></tr><tr><td></td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap>numBufs,</td></tr><tr><td></td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>bufs</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote><p>Closes an opened stream.&nbsp; For convenience, it will also delete the given buffer objects.&nbsp; The given buffer objects do not need to be ones given by the alureCreateStream functions.&nbsp; Requires an active context.</p><h4 class=CHeading>Returns</h4><p>AL_FALSE on error.</p></div></div></div>
+
+</div><!--Content-->
+
+
+<div id=Footer><a href="http://www.naturaldocs.org">Generated by Natural Docs</a></div><!--Footer-->
+
+
+<div id=Menu><div class=MTitle>ALURE<div class=MSubTitle>API Reference</div></div><div class=MEntry><div class=MFile><a href="alure-cpp.html">Main and Miscellanious</a></div></div><div class=MEntry><div class=MFile><a href="buffer-cpp.html">File Loading</a></div></div><div class=MEntry><div class=MFile id=MSelected>Streaming</div></div><div class=MEntry><div class=MFile><a href="istream-cpp.html">File I/<wbr>O</a></div></div><div class=MEntry><div class=MFile><a href="streamplay-cpp.html">Automatic Playback</a></div></div><div class=MEntry><div class=MGroup><a href="javascript:ToggleMenu('MGroupContent1')">Index</a><div class=MGroupContent id=MGroupContent1><div class=MEntry><div class=MIndex><a href="../index/General.html">Everything</a></div></div><div class=MEntry><div class=MIndex><a href="../index/Functions.html">Functions</a></div></div></div></div></div><script type="text/javascript"><!--
+var searchPanel = new SearchPanel("searchPanel", "HTML", "../search");
+--></script><div id=MSearchPanel class=MSearchPanelInactive><input type=text id=MSearchField value=Search onFocus="searchPanel.OnSearchFieldFocus(true)" onBlur="searchPanel.OnSearchFieldFocus(false)" onKeyUp="searchPanel.OnSearchFieldChange()"><select id=MSearchType onFocus="searchPanel.OnSearchTypeFocus(true)" onBlur="searchPanel.OnSearchTypeFocus(false)" onChange="searchPanel.OnSearchTypeChange()"><option  id=MSearchEverything selected value="General">Everything</option><option value="Functions">Functions</option></select></div></div><!--Menu-->
+
+
+
+<!--START_ND_TOOLTIPS-->
+<div class=CToolTip id="tt1"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALboolean ALURE_APIENTRY alureStreamSizeIsMicroSec(</td><td class=PType nowrap>ALboolean&nbsp;</td><td class=PParameter nowrap>useUS</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Specifies if the chunk size value given to the alureCreateStream functions is in bytes (default) or microseconds. </div></div><div class=CToolTip id="tt2"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters colspan=5>ALURE_API alureStream* ALURE_APIENTRY alureCreateStreamFromFile(</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap>const&nbsp;</td><td class=PType nowrap>ALchar&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>fname,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>chunkLength,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>numBufs,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>bufs</td></tr><tr><td class=PAfterParameters colspan=5>)</td></tr></table></td></tr></table></blockquote>Opens a file and sets it up for streaming. </div></div><div class=CToolTip id="tt3"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters colspan=5>ALURE_API alureStream* ALURE_APIENTRY alureCreateStreamFromMemory(</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap>const&nbsp;</td><td class=PType nowrap>ALubyte&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>fdata,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>length,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>chunkLength,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>numBufs,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>bufs</td></tr><tr><td class=PAfterParameters colspan=5>)</td></tr></table></td></tr></table></blockquote>Opens a file image from memory and sets it up for streaming, similar to alureCreateStreamFromFile. </div></div><div class=CToolTip id="tt4"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters colspan=5>ALURE_API alureStream* ALURE_APIENTRY alureCreateStreamFromStaticMemory(</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap>const&nbsp;</td><td class=PType nowrap>ALubyte&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>fdata,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>length,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>chunkLength,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>numBufs,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>bufs</td></tr><tr><td class=PAfterParameters colspan=5>)</td></tr></table></td></tr></table></blockquote>Identical to alureCreateStreamFromMemory, except the given memory is used directly and not duplicated. </div></div><div class=CToolTip id="tt5"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters colspan=4>ALURE_API alureStream* ALURE_APIENTRY alureCreateStreamFromCallback(</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>(*callback)(void *userdata, ALubyte *data, ALuint bytes),</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>void&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>userdata,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALenum&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>format,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>samplerate,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>chunkLength,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>numBufs,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>bufs</td></tr><tr><td class=PAfterParameters colspan=4>)</td></tr></table></td></tr></table></blockquote>Creates a stream using the specified callback to retrieve data. </div></div><div class=CToolTip id="tt6"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALsizei ALURE_APIENTRY alureGetStreamFrequency(</td><td class=PType nowrap>alureStream&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>stream</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Retrieves the frequency used by the given stream.</div></div><div class=CToolTip id="tt7"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALsizei ALURE_APIENTRY alureBufferDataFromStream(</td><td class=PType nowrap>alureStream&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>stream,</td></tr><tr><td></td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap>numBufs,</td></tr><tr><td></td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>bufs</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Buffers the given buffer objects with the next chunks of data from the stream. </div></div><div class=CToolTip id="tt8"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALboolean ALURE_APIENTRY alureRewindStream(</td><td class=PType nowrap>alureStream&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>stream</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Rewinds the stream so that the next alureBufferDataFromStream call will restart from the beginning of the audio file.</div></div><div class=CToolTip id="tt9"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALboolean ALURE_APIENTRY alureSetStreamOrder(</td><td class=PType nowrap>alureStream&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>stream,</td></tr><tr><td></td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap>order</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Skips the module decoder to the specified order, so following buffering calls will decode from the specified order. </div></div><div class=CToolTip id="tt10"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters colspan=5>ALURE_API ALboolean ALURE_APIENTRY alureSetStreamPatchset(</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>alureStream&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>stream,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap>const&nbsp;</td><td class=PType nowrap>ALchar&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>patchset</td></tr><tr><td class=PAfterParameters colspan=5>)</td></tr></table></td></tr></table></blockquote>Specifies the patchset to use for MIDI streams. </div></div><div class=CToolTip id="tt11"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API alureInt64 ALURE_APIENTRY alureGetStreamLength(</td><td class=PType nowrap>alureStream&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>stream</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Retrieves an approximate number of samples for the stream. </div></div><div class=CToolTip id="tt12"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALboolean ALURE_APIENTRY alureDestroyStream(</td><td class=PType nowrap>alureStream&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>stream,</td></tr><tr><td></td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap>numBufs,</td></tr><tr><td></td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>bufs</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Closes an opened stream. </div></div><!--END_ND_TOOLTIPS-->
+
+
+
+
+<div id=MSearchResultsWindow><iframe src="" frameborder=0 name=MSearchResults id=MSearchResults></iframe><a href="javascript:searchPanel.CloseResultsWindow()" id=MSearchResultsWindowClose>Close</a></div>
+
+
+<script language=JavaScript><!--
+if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
\ No newline at end of file
diff --git a/docs/html/files/streamplay-cpp.html b/docs/html/files/streamplay-cpp.html
new file mode 100644 (file)
index 0000000..b3a223e
--- /dev/null
@@ -0,0 +1,54 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+
+<html><head><title>Automatic Playback - ALURE</title><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script><script language=JavaScript src="../javascript/searchdata.js"></script></head><body class="ContentPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
+if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
+
+<!--  Generated by Natural Docs, version 1.4 -->
+<!--  http://www.naturaldocs.org  -->
+
+<!-- saved from url=(0026)http://www.naturaldocs.org -->
+
+
+
+
+<div id=Content><div class="CSection"><div class=CTopic id=MainTopic><h1 class=CTitle><a name="Automatic_Playback"></a>Automatic Playback</h1><div class=CBody><!--START_ND_SUMMARY--><div class=Summary><div class=STitle>Summary</div><div class=SBorder><table border=0 cellspacing=0 cellpadding=0 class=STable><tr class="SMain"><td class=SEntry><a href="#Automatic_Playback" >Automatic Playback</a></td><td class=SDescription></td></tr><tr class="SGroup SIndent1"><td class=SEntry><a href="#Functions" >Functions</a></td><td class=SDescription></td></tr><tr class="SFunction SIndent2 SMarked"><td class=SEntry><a href="#alurePlaySourceStream" id=link1 onMouseOver="ShowTip(event, 'tt1', 'link1')" onMouseOut="HideTip('tt1')">alurePlaySourceStream</a></td><td class=SDescription>Starts playing a stream, using the specified source ID. </td></tr><tr class="SFunction SIndent2"><td class=SEntry><a href="#alurePlaySource" id=link2 onMouseOver="ShowTip(event, 'tt2', 'link2')" onMouseOut="HideTip('tt2')">alurePlaySource</a></td><td class=SDescription>Plays the specified source ID and watches for it to stop. </td></tr><tr class="SFunction SIndent2 SMarked"><td class=SEntry><a href="#alureStopSource" id=link3 onMouseOver="ShowTip(event, 'tt3', 'link3')" onMouseOut="HideTip('tt3')">alureStopSource</a></td><td class=SDescription>Stops the specified source ID, and any associated stream. </td></tr><tr class="SFunction SIndent2"><td class=SEntry><a href="#alurePauseSource" id=link4 onMouseOver="ShowTip(event, 'tt4', 'link4')" onMouseOut="HideTip('tt4')">alurePauseSource</a></td><td class=SDescription>Pauses the specified source ID, and any associated stream. </td></tr><tr class="SFunction SIndent2 SMarked"><td class=SEntry><a href="#alureResumeSource" id=link5 onMouseOver="ShowTip(event, 'tt5', 'link5')" onMouseOut="HideTip('tt5')">alureResumeSource</a></td><td class=SDescription>Resumes the specified source ID after being paused.</td></tr><tr class="SFunction SIndent2"><td class=SEntry><a href="#alureUpdate" id=link6 onMouseOver="ShowTip(event, 'tt6', 'link6')" onMouseOut="HideTip('tt6')">alureUpdate</a></td><td class=SDescription>Updates the running list of streams, and checks for stopped sources. </td></tr><tr class="SFunction SIndent2 SMarked"><td class=SEntry><a href="#alureUpdateInterval" id=link7 onMouseOver="ShowTip(event, 'tt7', 'link7')" onMouseOut="HideTip('tt7')">alureUpdateInterval</a></td><td class=SDescription>Sets up a timer or thread to automatically call <a href="#alureUpdate" class=LFunction id=link8 onMouseOver="ShowTip(event, 'tt6', 'link8')" onMouseOut="HideTip('tt6')">alureUpdate</a> at the given interval, in seconds. </td></tr></table></div></div><!--END_ND_SUMMARY--></div></div></div>
+
+<div class="CGroup"><div class=CTopic><h3 class=CTitle><a name="Functions"></a>Functions</h3></div></div>
+
+<div class="CFunction"><div class=CTopic><h3 class=CTitle><a name="alurePlaySourceStream"></a>alurePlaySourceStream</h3><div class=CBody><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters colspan=4>ALURE_API ALboolean ALURE_APIENTRY alurePlaySourceStream(</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>source,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>alureStream&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>stream,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>numBufs,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>loopcount,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>void&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>(*eos_callback)(void *userdata, ALuint source),</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>void&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>userdata</td></tr><tr><td class=PAfterParameters colspan=4>)</td></tr></table></td></tr></table></blockquote><p>Starts playing a stream, using the specified source ID.&nbsp; A stream can only be played if it is not already playing.&nbsp; You must call <a href="#alureUpdate" class=LFunction id=link9 onMouseOver="ShowTip(event, 'tt6', 'link9')" onMouseOut="HideTip('tt6')">alureUpdate</a> at regular intervals to keep the stream playing, or else the stream will underrun and cause a break in the playback until an update call can restart it.&nbsp; It is also important that the current context is kept for <a href="#alureUpdate" class=LFunction id=link10 onMouseOver="ShowTip(event, 'tt6', 'link10')" onMouseOut="HideTip('tt6')">alureUpdate</a> calls if ALC_EXT_thread_local_context is not supported, otherwise the method may start calling OpenAL with invalid IDs.&nbsp; Note that checking the state of the specified source is not a good method to determine if a stream is playing.&nbsp; If an underrun occurs, the source will enter a stopped state until it is automatically restarted.&nbsp; Instead, set a flag using the callback to indicate the stream being stopped.</p><h4 class=CHeading>Parameters</h4><table border=0 cellspacing=0 cellpadding=0 class=CDescriptionList><tr><td class=CDLEntry>source</td><td class=CDLDescription>The source ID to play the stream with.&nbsp; Any buffers on the source will be unqueued.&nbsp; It is valid to set source properties not related to the buffer queue or playback state (ie. you may change the source&rsquo;s position, pitch, gain, etc, but you must not stop the source or queue/unqueue buffers on it).&nbsp; To pause the source, call <a href="#alurePauseSource" class=LFunction id=link11 onMouseOver="ShowTip(event, 'tt4', 'link11')" onMouseOut="HideTip('tt4')">alurePauseSource</a>.</td></tr><tr><td class=CDLEntry>stream</td><td class=CDLDescription>The stream to play.&nbsp; Any valid stream will work, although looping will only work if the stream can be rewound (eg. streams made with <a href="stream-cpp.html#alureCreateStreamFromCallback" class=LFunction id=link12 onMouseOver="ShowTip(event, 'tt8', 'link12')" onMouseOut="HideTip('tt8')">alureCreateStreamFromCallback</a> cannot loop, but will play for as long as the callback provides data).</td></tr><tr><td class=CDLEntry>numBufs</td><td class=CDLDescription>The number of buffers used to queue with the OpenAL source.&nbsp; Each buffer will be filled with the chunk length specified when the stream was created.&nbsp; This value must be at least 2.&nbsp; More buffers at a larger size will increase the time needed between updates, but at the cost of more memory usage.</td></tr><tr><td class=CDLEntry>loopcount</td><td class=CDLDescription>The number of times to loop the stream.&nbsp; When the stream reaches the end of processing, it will be rewound to continue buffering data.&nbsp; A value of -1 will cause the stream to loop indefinitely (or until <a href="#alureStopSource" class=LFunction id=link13 onMouseOver="ShowTip(event, 'tt3', 'link13')" onMouseOut="HideTip('tt3')">alureStopSource</a> is called).</td></tr><tr><td class=CDLEntry>eos_callback</td><td class=CDLDescription>This callback will be called when the stream reaches the end, no more loops are pending, and the source reaches a stopped state.&nbsp; It will also be called if an error occured and playback terminated.</td></tr><tr><td class=CDLEntry>userdata</td><td class=CDLDescription>An opaque user pointer passed to the callback.</td></tr></table><h4 class=CHeading>Returns</h4><p>AL_FALSE on error.</p><p><b>Version Added</b>: 1.1</p><h4 class=CHeading>See Also</h4><p><a href="#alureStopSource" class=LFunction id=link14 onMouseOver="ShowTip(event, 'tt3', 'link14')" onMouseOut="HideTip('tt3')">alureStopSource</a>, <a href="#alurePauseSource" class=LFunction id=link15 onMouseOver="ShowTip(event, 'tt4', 'link15')" onMouseOut="HideTip('tt4')">alurePauseSource</a>, <a href="#alureUpdate" class=LFunction id=link16 onMouseOver="ShowTip(event, 'tt6', 'link16')" onMouseOut="HideTip('tt6')">alureUpdate</a></p></div></div></div>
+
+<div class="CFunction"><div class=CTopic><h3 class=CTitle><a name="alurePlaySource"></a>alurePlaySource</h3><div class=CBody><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters colspan=4>ALURE_API ALboolean ALURE_APIENTRY alurePlaySource(</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>source,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>void&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>(*callback)(void *userdata, ALuint source),</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>void&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>userdata</td></tr><tr><td class=PAfterParameters colspan=4>)</td></tr></table></td></tr></table></blockquote><p>Plays the specified source ID and watches for it to stop.&nbsp; When the source enters an AL_STOPPED or AL_INITIAL state, the specified callback will be called by <a href="#alureUpdate" class=LFunction id=link17 onMouseOver="ShowTip(event, 'tt6', 'link17')" onMouseOut="HideTip('tt6')">alureUpdate</a> to alert the application.&nbsp; If ALC_EXT_thread_local_context is not supported, the current context must not be changed while the source is being watched (before the callback is called or <a href="#alureStopSource" class=LFunction id=link18 onMouseOver="ShowTip(event, 'tt3', 'link18')" onMouseOut="HideTip('tt3')">alureStopSource</a> is called).&nbsp; It also must not be deleted while being watched.</p><h4 class=CHeading>Parameters</h4><table border=0 cellspacing=0 cellpadding=0 class=CDescriptionList><tr><td class=CDLEntry>source</td><td class=CDLDescription>The source ID to play.&nbsp; As with <a href="#alurePlaySourceStream" class=LFunction id=link19 onMouseOver="ShowTip(event, 'tt1', 'link19')" onMouseOut="HideTip('tt1')">alurePlaySourceStream</a>, it is valid to set source properties not related to the playback state (ie. you may change a source&rsquo;s position, pitch, gain, etc).&nbsp; Pausing a source and restarting a paused source is allowed, and the callback will still be called when the source reaches an AL_STOPPED or AL_INITIAL state.</td></tr><tr><td class=CDLEntry>callback</td><td class=CDLDescription>The callback to be called when the source stops.</td></tr><tr><td class=CDLEntry>userdata</td><td class=CDLDescription>An opaque user pointer passed to the callback.</td></tr></table><h4 class=CHeading>Returns</h4><p>AL_FALSE on error.</p><p><b>Version Added</b>: 1.1</p><h4 class=CHeading>See Also</h4><p><a href="#alureStopSource" class=LFunction id=link20 onMouseOver="ShowTip(event, 'tt3', 'link20')" onMouseOut="HideTip('tt3')">alureStopSource</a>, <a href="#alureUpdate" class=LFunction id=link21 onMouseOver="ShowTip(event, 'tt6', 'link21')" onMouseOut="HideTip('tt6')">alureUpdate</a></p></div></div></div>
+
+<div class="CFunction"><div class=CTopic><h3 class=CTitle><a name="alureStopSource"></a>alureStopSource</h3><div class=CBody><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALboolean ALURE_APIENTRY alureStopSource(</td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameter nowrap>source,</td></tr><tr><td></td><td class=PType nowrap>ALboolean&nbsp;</td><td class=PParameter nowrap>run_callback</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote><p>Stops the specified source ID, and any associated stream.&nbsp; The previously specified callback will be invoked if &lsquo;run_callback&rsquo; is not AL_FALSE.&nbsp; Sources that were not started with <a href="#alurePlaySourceStream" class=LFunction id=link22 onMouseOver="ShowTip(event, 'tt1', 'link22')" onMouseOut="HideTip('tt1')">alurePlaySourceStream</a> or <a href="#alurePlaySource" class=LFunction id=link23 onMouseOver="ShowTip(event, 'tt2', 'link23')" onMouseOut="HideTip('tt2')">alurePlaySource</a> will still be stopped, but will not have any callback called for them.</p><h4 class=CHeading>Returns</h4><p>AL_FALSE on error.</p><p><b>Version Added</b>: 1.1</p><h4 class=CHeading>See Also</h4><p><a href="#alurePlaySourceStream" class=LFunction id=link24 onMouseOver="ShowTip(event, 'tt1', 'link24')" onMouseOut="HideTip('tt1')">alurePlaySourceStream</a>, <a href="#alurePlaySource" class=LFunction id=link25 onMouseOver="ShowTip(event, 'tt2', 'link25')" onMouseOut="HideTip('tt2')">alurePlaySource</a></p></div></div></div>
+
+<div class="CFunction"><div class=CTopic><h3 class=CTitle><a name="alurePauseSource"></a>alurePauseSource</h3><div class=CBody><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALboolean ALURE_APIENTRY alurePauseSource(</td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameter nowrap>source</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote><p>Pauses the specified source ID, and any associated stream.&nbsp; This is needed to avoid potential race conditions with sources that are playing a stream.</p><p>Note that it is possible for the specified source to become stopped, and any associated stream to finish, before this function is called, causing the callback to be delayed until after the function returns and <a href="#alureUpdate" class=LFunction id=link26 onMouseOver="ShowTip(event, 'tt6', 'link26')" onMouseOut="HideTip('tt6')">alureUpdate</a> detects the stopped source.</p><h4 class=CHeading>Returns</h4><p>AL_FALSE on error.</p><p><b>Version Added</b>: 1.1</p><h4 class=CHeading>See Also</h4><p><a href="#alureResumeSource" class=LFunction id=link27 onMouseOver="ShowTip(event, 'tt5', 'link27')" onMouseOut="HideTip('tt5')">alureResumeSource</a>, <a href="#alurePlaySourceStream" class=LFunction id=link28 onMouseOver="ShowTip(event, 'tt1', 'link28')" onMouseOut="HideTip('tt1')">alurePlaySourceStream</a>, <a href="#alurePlaySource" class=LFunction id=link29 onMouseOver="ShowTip(event, 'tt2', 'link29')" onMouseOut="HideTip('tt2')">alurePlaySource</a></p></div></div></div>
+
+<div class="CFunction"><div class=CTopic><h3 class=CTitle><a name="alureResumeSource"></a>alureResumeSource</h3><div class=CBody><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALboolean ALURE_APIENTRY alureResumeSource(</td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameter nowrap>source</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote><p>Resumes the specified source ID after being paused.</p><h4 class=CHeading>Returns</h4><p>AL_FALSE on error.</p><p><b>Version Added</b>: 1.1</p><h4 class=CHeading>See Also</h4><p><a href="#alurePauseSource" class=LFunction id=link30 onMouseOver="ShowTip(event, 'tt4', 'link30')" onMouseOut="HideTip('tt4')">alurePauseSource</a></p></div></div></div>
+
+<div class="CFunction"><div class=CTopic><h3 class=CTitle><a name="alureUpdate"></a>alureUpdate</h3><div class=CBody><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API void ALURE_APIENTRY alureUpdate(</td><td class=PParameter nowrap>void</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote><p>Updates the running list of streams, and checks for stopped sources.&nbsp; This makes sure that sources played with <a href="#alurePlaySourceStream" class=LFunction id=link31 onMouseOver="ShowTip(event, 'tt1', 'link31')" onMouseOut="HideTip('tt1')">alurePlaySourceStream</a> are kept fed from their associated stream, and sources played with <a href="#alurePlaySource" class=LFunction id=link32 onMouseOver="ShowTip(event, 'tt2', 'link32')" onMouseOut="HideTip('tt2')">alurePlaySource</a> are still playing.&nbsp; It will call their callbacks as needed.</p><p><b>Version Added</b>: 1.1</p><h4 class=CHeading>See Also</h4><p><a href="#alurePlaySourceStream" class=LFunction id=link33 onMouseOver="ShowTip(event, 'tt1', 'link33')" onMouseOut="HideTip('tt1')">alurePlaySourceStream</a>, <a href="#alurePlaySource" class=LFunction id=link34 onMouseOver="ShowTip(event, 'tt2', 'link34')" onMouseOut="HideTip('tt2')">alurePlaySource</a></p></div></div></div>
+
+<div class="CFunction"><div class=CTopic><h3 class=CTitle><a name="alureUpdateInterval"></a>alureUpdateInterval</h3><div class=CBody><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALboolean ALURE_APIENTRY alureUpdateInterval(</td><td class=PType nowrap>ALfloat&nbsp;</td><td class=PParameter nowrap>interval</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote><p>Sets up a timer or thread to automatically call <a href="#alureUpdate" class=LFunction id=link35 onMouseOver="ShowTip(event, 'tt6', 'link35')" onMouseOut="HideTip('tt6')">alureUpdate</a> at the given interval, in seconds.&nbsp; If the timer or thread is already running, the update interval will be modified.&nbsp; A 0 or negative interval will stop <a href="#alureUpdate" class=LFunction id=link36 onMouseOver="ShowTip(event, 'tt6', 'link36')" onMouseOut="HideTip('tt6')">alureUpdate</a> from being called.</p><h4 class=CHeading>Returns</h4><p>AL_FALSE on error.</p><p><b>Version Added</b>: 1.1</p><h4 class=CHeading>See Also</h4><p><a href="#alureUpdate" class=LFunction id=link37 onMouseOver="ShowTip(event, 'tt6', 'link37')" onMouseOut="HideTip('tt6')">alureUpdate</a></p></div></div></div>
+
+</div><!--Content-->
+
+
+<div id=Footer><a href="http://www.naturaldocs.org">Generated by Natural Docs</a></div><!--Footer-->
+
+
+<div id=Menu><div class=MTitle>ALURE<div class=MSubTitle>API Reference</div></div><div class=MEntry><div class=MFile><a href="alure-cpp.html">Main and Miscellanious</a></div></div><div class=MEntry><div class=MFile><a href="buffer-cpp.html">File Loading</a></div></div><div class=MEntry><div class=MFile><a href="stream-cpp.html">Streaming</a></div></div><div class=MEntry><div class=MFile><a href="istream-cpp.html">File I/<wbr>O</a></div></div><div class=MEntry><div class=MFile id=MSelected>Automatic Playback</div></div><div class=MEntry><div class=MGroup><a href="javascript:ToggleMenu('MGroupContent1')">Index</a><div class=MGroupContent id=MGroupContent1><div class=MEntry><div class=MIndex><a href="../index/General.html">Everything</a></div></div><div class=MEntry><div class=MIndex><a href="../index/Functions.html">Functions</a></div></div></div></div></div><script type="text/javascript"><!--
+var searchPanel = new SearchPanel("searchPanel", "HTML", "../search");
+--></script><div id=MSearchPanel class=MSearchPanelInactive><input type=text id=MSearchField value=Search onFocus="searchPanel.OnSearchFieldFocus(true)" onBlur="searchPanel.OnSearchFieldFocus(false)" onKeyUp="searchPanel.OnSearchFieldChange()"><select id=MSearchType onFocus="searchPanel.OnSearchTypeFocus(true)" onBlur="searchPanel.OnSearchTypeFocus(false)" onChange="searchPanel.OnSearchTypeChange()"><option  id=MSearchEverything selected value="General">Everything</option><option value="Functions">Functions</option></select></div></div><!--Menu-->
+
+
+
+<!--START_ND_TOOLTIPS-->
+<div class=CToolTip id="tt1"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters colspan=4>ALURE_API ALboolean ALURE_APIENTRY alurePlaySourceStream(</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>source,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>alureStream&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>stream,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>numBufs,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>loopcount,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>void&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>(*eos_callback)(void *userdata, ALuint source),</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>void&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>userdata</td></tr><tr><td class=PAfterParameters colspan=4>)</td></tr></table></td></tr></table></blockquote>Starts playing a stream, using the specified source ID. </div></div><div class=CToolTip id="tt2"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters colspan=4>ALURE_API ALboolean ALURE_APIENTRY alurePlaySource(</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>source,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>void&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>(*callback)(void *userdata, ALuint source),</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>void&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>userdata</td></tr><tr><td class=PAfterParameters colspan=4>)</td></tr></table></td></tr></table></blockquote>Plays the specified source ID and watches for it to stop. </div></div><div class=CToolTip id="tt3"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALboolean ALURE_APIENTRY alureStopSource(</td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameter nowrap>source,</td></tr><tr><td></td><td class=PType nowrap>ALboolean&nbsp;</td><td class=PParameter nowrap>run_callback</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Stops the specified source ID, and any associated stream. </div></div><div class=CToolTip id="tt4"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALboolean ALURE_APIENTRY alurePauseSource(</td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameter nowrap>source</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Pauses the specified source ID, and any associated stream. </div></div><div class=CToolTip id="tt5"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALboolean ALURE_APIENTRY alureResumeSource(</td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameter nowrap>source</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Resumes the specified source ID after being paused.</div></div><div class=CToolTip id="tt6"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API void ALURE_APIENTRY alureUpdate(</td><td class=PParameter nowrap>void</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Updates the running list of streams, and checks for stopped sources. </div></div><div class=CToolTip id="tt7"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALboolean ALURE_APIENTRY alureUpdateInterval(</td><td class=PType nowrap>ALfloat&nbsp;</td><td class=PParameter nowrap>interval</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Sets up a timer or thread to automatically call alureUpdate at the given interval, in seconds. </div></div><div class=CToolTip id="tt8"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters colspan=4>ALURE_API alureStream* ALURE_APIENTRY alureCreateStreamFromCallback(</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>(*callback)(void *userdata, ALubyte *data, ALuint bytes),</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>void&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>userdata,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALenum&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>format,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>samplerate,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>chunkLength,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>numBufs,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>bufs</td></tr><tr><td class=PAfterParameters colspan=4>)</td></tr></table></td></tr></table></blockquote>Creates a stream using the specified callback to retrieve data. </div></div><!--END_ND_TOOLTIPS-->
+
+
+
+
+<div id=MSearchResultsWindow><iframe src="" frameborder=0 name=MSearchResults id=MSearchResults></iframe><a href="javascript:searchPanel.CloseResultsWindow()" id=MSearchResultsWindowClose>Close</a></div>
+
+
+<script language=JavaScript><!--
+if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
\ No newline at end of file
diff --git a/docs/html/index.html b/docs/html/index.html
new file mode 100644 (file)
index 0000000..58be54c
--- /dev/null
@@ -0,0 +1 @@
+<html><head><meta http-equiv="Refresh" CONTENT="0; URL=files/alure-cpp.html"></head></html>
\ No newline at end of file
diff --git a/docs/html/index/Functions.html b/docs/html/index/Functions.html
new file mode 100644 (file)
index 0000000..b0aa6f5
--- /dev/null
@@ -0,0 +1,33 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+
+<html><head><title>Function Index - ALURE</title><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script><script language=JavaScript src="../javascript/searchdata.js"></script></head><body class="IndexPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
+if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
+
+<!--  Generated by Natural Docs, version 1.4 -->
+<!--  http://www.naturaldocs.org  -->
+
+<!-- saved from url=(0026)http://www.naturaldocs.org -->
+
+
+
+
+<div id=Index><div class=IPageTitle>Function Index</div><div class=INavigationBar>$#! &middot; 0-9 &middot; <a href="#A">A</a> &middot; B &middot; C &middot; D &middot; E &middot; F &middot; G &middot; H &middot; I &middot; J &middot; K &middot; L &middot; M &middot; N &middot; O &middot; P &middot; Q &middot; R &middot; S &middot; T &middot; U &middot; V &middot; W &middot; X &middot; Y &middot; Z</div><table border=0 cellspacing=0 cellpadding=0><tr><td class=IHeading id=IFirstHeading><a name="A"></a>A</td><td></td></tr><tr><td class=ISymbolPrefix id=IFirstSymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/buffer-cpp.html#alureBufferDataFromFile" id=link1 onMouseOver="ShowTip(event, 'tt1', 'link1')" onMouseOut="HideTip('tt1')" class=ISymbol>alureBufferDataFromFile</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/buffer-cpp.html#alureBufferDataFromMemory" id=link2 onMouseOver="ShowTip(event, 'tt2', 'link2')" onMouseOut="HideTip('tt2')" class=ISymbol>alureBufferDataFromMemory</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/stream-cpp.html#alureBufferDataFromStream" id=link3 onMouseOver="ShowTip(event, 'tt3', 'link3')" onMouseOut="HideTip('tt3')" class=ISymbol>alureBufferDataFromStream</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/buffer-cpp.html#alureCreateBufferFromFile" id=link4 onMouseOver="ShowTip(event, 'tt4', 'link4')" onMouseOut="HideTip('tt4')" class=ISymbol>alureCreateBufferFromFile</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/buffer-cpp.html#alureCreateBufferFromMemory" id=link5 onMouseOver="ShowTip(event, 'tt5', 'link5')" onMouseOut="HideTip('tt5')" class=ISymbol>alureCreateBufferFromMemory</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/stream-cpp.html#alureCreateStreamFromCallback" id=link6 onMouseOver="ShowTip(event, 'tt6', 'link6')" onMouseOut="HideTip('tt6')" class=ISymbol>alureCreateStreamFromCallback</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/stream-cpp.html#alureCreateStreamFromFile" id=link7 onMouseOver="ShowTip(event, 'tt7', 'link7')" onMouseOut="HideTip('tt7')" class=ISymbol>alureCreateStreamFromFile</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/stream-cpp.html#alureCreateStreamFromMemory" id=link8 onMouseOver="ShowTip(event, 'tt8', 'link8')" onMouseOut="HideTip('tt8')" class=ISymbol>alureCreateStreamFromMemory</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/stream-cpp.html#alureCreateStreamFromStaticMemory" id=link9 onMouseOver="ShowTip(event, 'tt9', 'link9')" onMouseOut="HideTip('tt9')" class=ISymbol>alureCreateStreamFromStaticMemory</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/stream-cpp.html#alureDestroyStream" id=link10 onMouseOver="ShowTip(event, 'tt10', 'link10')" onMouseOut="HideTip('tt10')" class=ISymbol>alureDestroyStream</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/alure-cpp.html#alureFreeDeviceNames" id=link11 onMouseOver="ShowTip(event, 'tt11', 'link11')" onMouseOut="HideTip('tt11')" class=ISymbol>alureFreeDeviceNames</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/alure-cpp.html#alureGetDeviceNames" id=link12 onMouseOver="ShowTip(event, 'tt12', 'link12')" onMouseOut="HideTip('tt12')" class=ISymbol>alureGetDeviceNames</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/alure-cpp.html#alureGetErrorString" id=link13 onMouseOver="ShowTip(event, 'tt13', 'link13')" onMouseOut="HideTip('tt13')" class=ISymbol>alureGetErrorString</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/alure-cpp.html#alureGetProcAddress" id=link14 onMouseOver="ShowTip(event, 'tt14', 'link14')" onMouseOut="HideTip('tt14')" class=ISymbol>alureGetProcAddress</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/alure-cpp.html#alureGetSampleFormat" id=link15 onMouseOver="ShowTip(event, 'tt15', 'link15')" onMouseOut="HideTip('tt15')" class=ISymbol>alureGetSampleFormat</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/stream-cpp.html#alureGetStreamFrequency" id=link16 onMouseOver="ShowTip(event, 'tt16', 'link16')" onMouseOut="HideTip('tt16')" class=ISymbol>alureGetStreamFrequency</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/stream-cpp.html#alureGetStreamLength" id=link17 onMouseOver="ShowTip(event, 'tt17', 'link17')" onMouseOut="HideTip('tt17')" class=ISymbol>alureGetStreamLength</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/alure-cpp.html#alureGetVersion" id=link18 onMouseOver="ShowTip(event, 'tt18', 'link18')" onMouseOut="HideTip('tt18')" class=ISymbol>alureGetVersion</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/alure-cpp.html#alureInitDevice" id=link19 onMouseOver="ShowTip(event, 'tt19', 'link19')" onMouseOut="HideTip('tt19')" class=ISymbol>alureInitDevice</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/alure-cpp.html#alureInstallDecodeCallbacks" id=link20 onMouseOver="ShowTip(event, 'tt20', 'link20')" onMouseOut="HideTip('tt20')" class=ISymbol>alureInstallDecodeCallbacks</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/streamplay-cpp.html#alurePauseSource" id=link21 onMouseOver="ShowTip(event, 'tt21', 'link21')" onMouseOut="HideTip('tt21')" class=ISymbol>alurePauseSource</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/streamplay-cpp.html#alurePlaySource" id=link22 onMouseOver="ShowTip(event, 'tt22', 'link22')" onMouseOut="HideTip('tt22')" class=ISymbol>alurePlaySource</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/streamplay-cpp.html#alurePlaySourceStream" id=link23 onMouseOver="ShowTip(event, 'tt23', 'link23')" onMouseOut="HideTip('tt23')" class=ISymbol>alurePlaySourceStream</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/streamplay-cpp.html#alureResumeSource" id=link24 onMouseOver="ShowTip(event, 'tt24', 'link24')" onMouseOut="HideTip('tt24')" class=ISymbol>alureResumeSource</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/stream-cpp.html#alureRewindStream" id=link25 onMouseOver="ShowTip(event, 'tt25', 'link25')" onMouseOut="HideTip('tt25')" class=ISymbol>alureRewindStream</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/istream-cpp.html#alureSetIOCallbacks" id=link26 onMouseOver="ShowTip(event, 'tt26', 'link26')" onMouseOut="HideTip('tt26')" class=ISymbol>alureSetIOCallbacks</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/stream-cpp.html#alureSetStreamOrder" id=link27 onMouseOver="ShowTip(event, 'tt27', 'link27')" onMouseOut="HideTip('tt27')" class=ISymbol>alureSetStreamOrder</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/stream-cpp.html#alureSetStreamPatchset" id=link28 onMouseOver="ShowTip(event, 'tt28', 'link28')" onMouseOut="HideTip('tt28')" class=ISymbol>alureSetStreamPatchset</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/alure-cpp.html#alureShutdownDevice" id=link29 onMouseOver="ShowTip(event, 'tt29', 'link29')" onMouseOut="HideTip('tt29')" class=ISymbol>alureShutdownDevice</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/alure-cpp.html#alureSleep" id=link30 onMouseOver="ShowTip(event, 'tt30', 'link30')" onMouseOut="HideTip('tt30')" class=ISymbol>alureSleep</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/streamplay-cpp.html#alureStopSource" id=link31 onMouseOver="ShowTip(event, 'tt31', 'link31')" onMouseOut="HideTip('tt31')" class=ISymbol>alureStopSource</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/stream-cpp.html#alureStreamSizeIsMicroSec" id=link32 onMouseOver="ShowTip(event, 'tt32', 'link32')" onMouseOut="HideTip('tt32')" class=ISymbol>alureStreamSizeIsMicroSec</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/streamplay-cpp.html#alureUpdate" id=link33 onMouseOver="ShowTip(event, 'tt33', 'link33')" onMouseOut="HideTip('tt33')" class=ISymbol>alureUpdate</a></td></tr><tr><td class=ISymbolPrefix id=ILastSymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/streamplay-cpp.html#alureUpdateInterval" id=link34 onMouseOver="ShowTip(event, 'tt34', 'link34')" onMouseOut="HideTip('tt34')" class=ISymbol>alureUpdateInterval</a></td></tr></table>
+<!--START_ND_TOOLTIPS-->
+<div class=CToolTip id="tt1"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters colspan=5>ALURE_API ALboolean ALURE_APIENTRY alureBufferDataFromFile(</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap>const&nbsp;</td><td class=PType nowrap>ALchar&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>fname,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>buffer</td></tr><tr><td class=PAfterParameters colspan=5>)</td></tr></table></td></tr></table></blockquote>Loads the given file into an existing OpenAL buffer object. </div></div><div class=CToolTip id="tt2"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters colspan=5>ALURE_API ALboolean ALURE_APIENTRY alureBufferDataFromMemory(</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap>const&nbsp;</td><td class=PType nowrap>ALubyte&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>fdata,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>length,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>buffer</td></tr><tr><td class=PAfterParameters colspan=5>)</td></tr></table></td></tr></table></blockquote>Loads a file image from memory into an existing OpenAL buffer object, similar to alureBufferDataFromFile. </div></div><div class=CToolTip id="tt3"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALsizei ALURE_APIENTRY alureBufferDataFromStream(</td><td class=PType nowrap>alureStream&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>stream,</td></tr><tr><td></td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap>numBufs,</td></tr><tr><td></td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>bufs</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Buffers the given buffer objects with the next chunks of data from the stream. </div></div><div class=CToolTip id="tt4"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALuint ALURE_APIENTRY alureCreateBufferFromFile(</td><td class=PTypePrefix nowrap>const&nbsp;</td><td class=PType nowrap>ALchar&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>fname</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Loads the given file into a new OpenAL buffer object. </div></div><div class=CToolTip id="tt5"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters colspan=5>ALURE_API ALuint ALURE_APIENTRY alureCreateBufferFromMemory(</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap>const&nbsp;</td><td class=PType nowrap>ALubyte&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>fdata,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>length</td></tr><tr><td class=PAfterParameters colspan=5>)</td></tr></table></td></tr></table></blockquote>Loads a file image from memory into a new OpenAL buffer object, similar to alureCreateBufferFromFile. </div></div><div class=CToolTip id="tt6"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters colspan=4>ALURE_API alureStream* ALURE_APIENTRY alureCreateStreamFromCallback(</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>(*callback)(void *userdata, ALubyte *data, ALuint bytes),</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>void&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>userdata,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALenum&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>format,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>samplerate,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>chunkLength,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>numBufs,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>bufs</td></tr><tr><td class=PAfterParameters colspan=4>)</td></tr></table></td></tr></table></blockquote>Creates a stream using the specified callback to retrieve data. </div></div><div class=CToolTip id="tt7"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters colspan=5>ALURE_API alureStream* ALURE_APIENTRY alureCreateStreamFromFile(</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap>const&nbsp;</td><td class=PType nowrap>ALchar&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>fname,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>chunkLength,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>numBufs,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>bufs</td></tr><tr><td class=PAfterParameters colspan=5>)</td></tr></table></td></tr></table></blockquote>Opens a file and sets it up for streaming. </div></div><div class=CToolTip id="tt8"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters colspan=5>ALURE_API alureStream* ALURE_APIENTRY alureCreateStreamFromMemory(</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap>const&nbsp;</td><td class=PType nowrap>ALubyte&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>fdata,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>length,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>chunkLength,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>numBufs,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>bufs</td></tr><tr><td class=PAfterParameters colspan=5>)</td></tr></table></td></tr></table></blockquote>Opens a file image from memory and sets it up for streaming, similar to alureCreateStreamFromFile. </div></div><div class=CToolTip id="tt9"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters colspan=5>ALURE_API alureStream* ALURE_APIENTRY alureCreateStreamFromStaticMemory(</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap>const&nbsp;</td><td class=PType nowrap>ALubyte&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>fdata,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>length,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>chunkLength,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>numBufs,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>bufs</td></tr><tr><td class=PAfterParameters colspan=5>)</td></tr></table></td></tr></table></blockquote>Identical to alureCreateStreamFromMemory, except the given memory is used directly and not duplicated. </div></div><div class=CToolTip id="tt10"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALboolean ALURE_APIENTRY alureDestroyStream(</td><td class=PType nowrap>alureStream&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>stream,</td></tr><tr><td></td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap>numBufs,</td></tr><tr><td></td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>bufs</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Closes an opened stream. </div></div><div class=CToolTip id="tt11"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALvoid ALURE_APIENTRY alureFreeDeviceNames(</td><td class=PTypePrefix nowrap>const&nbsp;</td><td class=PType nowrap>ALCchar&nbsp;</td><td class=PParameterPrefix nowrap>**</td><td class=PParameter nowrap>names</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Frees the device name array returned from alureGetDeviceNames.</div></div><div class=CToolTip id="tt12"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API const ALCchar** ALURE_APIENTRY alureGetDeviceNames(</td><td class=PType nowrap>ALCboolean&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap>all,</td></tr><tr><td></td><td class=PType nowrap>ALCsizei&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>count</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Gets an array of device name strings from OpenAL. </div></div><div class=CToolTip id="tt13"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API const ALchar* ALURE_APIENTRY alureGetErrorString(</td><td class=PParameter nowrap>void</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Returns a string describing the last error encountered.</div></div><div class=CToolTip id="tt14"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API void* ALURE_APIENTRY alureGetProcAddress(</td><td class=PTypePrefix nowrap>const&nbsp;</td><td class=PType nowrap>ALchar&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>funcname</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Returns a pointer for the named ALURE function.</div></div><div class=CToolTip id="tt15"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALenum ALURE_APIENTRY alureGetSampleFormat(</td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameter nowrap>channels,</td></tr><tr><td></td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameter nowrap>bits,</td></tr><tr><td></td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameter nowrap>floatbits</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Retrieves an OpenAL format for the given sample format. </div></div><div class=CToolTip id="tt16"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALsizei ALURE_APIENTRY alureGetStreamFrequency(</td><td class=PType nowrap>alureStream&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>stream</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Retrieves the frequency used by the given stream.</div></div><div class=CToolTip id="tt17"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API alureInt64 ALURE_APIENTRY alureGetStreamLength(</td><td class=PType nowrap>alureStream&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>stream</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Retrieves an approximate number of samples for the stream. </div></div><div class=CToolTip id="tt18"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API void ALURE_APIENTRY alureGetVersion(</td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>major,</td></tr><tr><td></td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>minor</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Stores the major and minor version of the library. </div></div><div class=CToolTip id="tt19"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALboolean ALURE_APIENTRY alureInitDevice(</td><td class=PTypePrefix nowrap>const&nbsp;</td><td class=PType nowrap>ALCchar&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>name,</td></tr><tr><td></td><td class=PTypePrefix nowrap>const&nbsp;</td><td class=PType nowrap>ALCint&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>attribs</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Opens the named device, creates a context with the given attributes, and sets that context as current. </div></div><div class=CToolTip id="tt20"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters colspan=4>ALURE_API ALboolean ALURE_APIENTRY alureInstallDecodeCallbacks(</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALint&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>index,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>void&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>(*open_file)(const ALchar *filename),</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>void&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>(*open_memory)(const ALubyte *data, ALuint length),</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALboolean&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>(*get_format)(void *instance, ALenum *format, ALuint *samplerate, ALuint *blocksize),</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>(*decode)(void *instance, ALubyte *data, ALuint bytes),</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALboolean&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>(*rewind)(void *instance),</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>void&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>(*close)(void *instance)</td></tr><tr><td class=PAfterParameters colspan=4>)</td></tr></table></td></tr></table></blockquote>Installs callbacks to enable ALURE to handle more file types. </div></div><div class=CToolTip id="tt21"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALboolean ALURE_APIENTRY alurePauseSource(</td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameter nowrap>source</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Pauses the specified source ID, and any associated stream. </div></div><div class=CToolTip id="tt22"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters colspan=4>ALURE_API ALboolean ALURE_APIENTRY alurePlaySource(</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>source,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>void&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>(*callback)(void *userdata, ALuint source),</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>void&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>userdata</td></tr><tr><td class=PAfterParameters colspan=4>)</td></tr></table></td></tr></table></blockquote>Plays the specified source ID and watches for it to stop. </div></div><div class=CToolTip id="tt23"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters colspan=4>ALURE_API ALboolean ALURE_APIENTRY alurePlaySourceStream(</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>source,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>alureStream&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>stream,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>numBufs,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>loopcount,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>void&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>(*eos_callback)(void *userdata, ALuint source),</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>void&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>userdata</td></tr><tr><td class=PAfterParameters colspan=4>)</td></tr></table></td></tr></table></blockquote>Starts playing a stream, using the specified source ID. </div></div><div class=CToolTip id="tt24"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALboolean ALURE_APIENTRY alureResumeSource(</td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameter nowrap>source</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Resumes the specified source ID after being paused.</div></div><div class=CToolTip id="tt25"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALboolean ALURE_APIENTRY alureRewindStream(</td><td class=PType nowrap>alureStream&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>stream</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Rewinds the stream so that the next alureBufferDataFromStream call will restart from the beginning of the audio file.</div></div><div class=CToolTip id="tt26"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters colspan=4>ALURE_API ALboolean ALURE_APIENTRY alureSetIOCallbacks(</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>void&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>(*open)(const char *filename, ALuint mode),</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>void&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>(*close)(void *handle),</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>(*read)(void *handle, ALubyte *buf, ALuint bytes),</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>(*write)(void *handle, const ALubyte *buf, ALuint bytes),</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>alureInt64&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>(*seek)(void *handle, alureInt64 offset, int whence)</td></tr><tr><td class=PAfterParameters colspan=4>)</td></tr></table></td></tr></table></blockquote>Provides callbacks for alternative methods to handle file I/O. </div></div><div class=CToolTip id="tt27"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALboolean ALURE_APIENTRY alureSetStreamOrder(</td><td class=PType nowrap>alureStream&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>stream,</td></tr><tr><td></td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap>order</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Skips the module decoder to the specified order, so following buffering calls will decode from the specified order. </div></div><div class=CToolTip id="tt28"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters colspan=5>ALURE_API ALboolean ALURE_APIENTRY alureSetStreamPatchset(</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>alureStream&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>stream,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap>const&nbsp;</td><td class=PType nowrap>ALchar&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>patchset</td></tr><tr><td class=PAfterParameters colspan=5>)</td></tr></table></td></tr></table></blockquote>Specifies the patchset to use for MIDI streams. </div></div><div class=CToolTip id="tt29"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALboolean ALURE_APIENTRY alureShutdownDevice(</td><td class=PParameter nowrap>void</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Destroys the current context and closes its associated device.</div></div><div class=CToolTip id="tt30"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALboolean ALURE_APIENTRY alureSleep(</td><td class=PType nowrap>ALfloat&nbsp;</td><td class=PParameter nowrap>duration</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Rests the calling thread for the given number of seconds.</div></div><div class=CToolTip id="tt31"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALboolean ALURE_APIENTRY alureStopSource(</td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameter nowrap>source,</td></tr><tr><td></td><td class=PType nowrap>ALboolean&nbsp;</td><td class=PParameter nowrap>run_callback</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Stops the specified source ID, and any associated stream. </div></div><div class=CToolTip id="tt32"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALboolean ALURE_APIENTRY alureStreamSizeIsMicroSec(</td><td class=PType nowrap>ALboolean&nbsp;</td><td class=PParameter nowrap>useUS</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Specifies if the chunk size value given to the alureCreateStream functions is in bytes (default) or microseconds. </div></div><div class=CToolTip id="tt33"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API void ALURE_APIENTRY alureUpdate(</td><td class=PParameter nowrap>void</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Updates the running list of streams, and checks for stopped sources. </div></div><div class=CToolTip id="tt34"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALboolean ALURE_APIENTRY alureUpdateInterval(</td><td class=PType nowrap>ALfloat&nbsp;</td><td class=PParameter nowrap>interval</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Sets up a timer or thread to automatically call alureUpdate at the given interval, in seconds. </div></div><!--END_ND_TOOLTIPS-->
+
+</div><!--Index-->
+
+
+<div id=Footer><a href="http://www.naturaldocs.org">Generated by Natural Docs</a></div><!--Footer-->
+
+
+<div id=Menu><div class=MTitle>ALURE<div class=MSubTitle>API Reference</div></div><div class=MEntry><div class=MFile><a href="../files/alure-cpp.html">Main and Miscellanious</a></div></div><div class=MEntry><div class=MFile><a href="../files/buffer-cpp.html">File Loading</a></div></div><div class=MEntry><div class=MFile><a href="../files/stream-cpp.html">Streaming</a></div></div><div class=MEntry><div class=MFile><a href="../files/istream-cpp.html">File I/<wbr>O</a></div></div><div class=MEntry><div class=MFile><a href="../files/streamplay-cpp.html">Automatic Playback</a></div></div><div class=MEntry><div class=MGroup><a href="javascript:ToggleMenu('MGroupContent1')">Index</a><div class=MGroupContent id=MGroupContent1><div class=MEntry><div class=MIndex><a href="General.html">Everything</a></div></div><div class=MEntry><div class=MIndex id=MSelected>Functions</div></div></div></div></div><script type="text/javascript"><!--
+var searchPanel = new SearchPanel("searchPanel", "HTML", "../search");
+--></script><div id=MSearchPanel class=MSearchPanelInactive><input type=text id=MSearchField value=Search onFocus="searchPanel.OnSearchFieldFocus(true)" onBlur="searchPanel.OnSearchFieldFocus(false)" onKeyUp="searchPanel.OnSearchFieldChange()"><select id=MSearchType onFocus="searchPanel.OnSearchTypeFocus(true)" onBlur="searchPanel.OnSearchTypeFocus(false)" onChange="searchPanel.OnSearchTypeChange()"><option  id=MSearchEverything selected value="General">Everything</option><option value="Functions">Functions</option></select></div></div><!--Menu-->
+
+
+<div id=MSearchResultsWindow><iframe src="" frameborder=0 name=MSearchResults id=MSearchResults></iframe><a href="javascript:searchPanel.CloseResultsWindow()" id=MSearchResultsWindowClose>Close</a></div>
+
+
+<script language=JavaScript><!--
+if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
\ No newline at end of file
diff --git a/docs/html/index/General.html b/docs/html/index/General.html
new file mode 100644 (file)
index 0000000..feb2463
--- /dev/null
@@ -0,0 +1,45 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+
+<html><head><title>Index - ALURE</title><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script><script language=JavaScript src="../javascript/searchdata.js"></script></head><body class="IndexPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
+if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
+
+<!--  Generated by Natural Docs, version 1.4 -->
+<!--  http://www.naturaldocs.org  -->
+
+<!-- saved from url=(0026)http://www.naturaldocs.org -->
+
+
+
+
+<div id=Index><div class=IPageTitle>Index</div><div class=INavigationBar>$#! &middot; 0-9 &middot; <a href="#A">A</a> &middot; B &middot; C &middot; D &middot; E &middot; <a href="#F">F</a> &middot; G &middot; H &middot; I &middot; J &middot; K &middot; L &middot; <a href="#M">M</a> &middot; N &middot; O &middot; P &middot; Q &middot; R &middot; <a href="#S">S</a> &middot; T &middot; U &middot; V &middot; W &middot; X &middot; Y &middot; Z</div><table border=0 cellspacing=0 cellpadding=0><tr><td class=IHeading id=IFirstHeading><a name="A"></a>A</td><td></td></tr><tr><td class=ISymbolPrefix id=IFirstSymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/buffer-cpp.html#alureBufferDataFromFile" id=link1 onMouseOver="ShowTip(event, 'tt1', 'link1')" onMouseOut="HideTip('tt1')" class=ISymbol>alureBufferDataFromFile</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/buffer-cpp.html#alureBufferDataFromMemory" id=link2 onMouseOver="ShowTip(event, 'tt2', 'link2')" onMouseOut="HideTip('tt2')" class=ISymbol>alureBufferDataFromMemory</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/stream-cpp.html#alureBufferDataFromStream" id=link3 onMouseOver="ShowTip(event, 'tt3', 'link3')" onMouseOut="HideTip('tt3')" class=ISymbol>alureBufferDataFromStream</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/buffer-cpp.html#alureCreateBufferFromFile" id=link4 onMouseOver="ShowTip(event, 'tt4', 'link4')" onMouseOut="HideTip('tt4')" class=ISymbol>alureCreateBufferFromFile</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/buffer-cpp.html#alureCreateBufferFromMemory" id=link5 onMouseOver="ShowTip(event, 'tt5', 'link5')" onMouseOut="HideTip('tt5')" class=ISymbol>alureCreateBufferFromMemory</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/stream-cpp.html#alureCreateStreamFromCallback" id=link6 onMouseOver="ShowTip(event, 'tt6', 'link6')" onMouseOut="HideTip('tt6')" class=ISymbol>alureCreateStreamFromCallback</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/stream-cpp.html#alureCreateStreamFromFile" id=link7 onMouseOver="ShowTip(event, 'tt7', 'link7')" onMouseOut="HideTip('tt7')" class=ISymbol>alureCreateStreamFromFile</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/stream-cpp.html#alureCreateStreamFromMemory" id=link8 onMouseOver="ShowTip(event, 'tt8', 'link8')" onMouseOut="HideTip('tt8')" class=ISymbol>alureCreateStreamFromMemory</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/stream-cpp.html#alureCreateStreamFromStaticMemory" id=link9 onMouseOver="ShowTip(event, 'tt9', 'link9')" onMouseOut="HideTip('tt9')" class=ISymbol>alureCreateStreamFromStaticMemory</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/stream-cpp.html#alureDestroyStream" id=link10 onMouseOver="ShowTip(event, 'tt10', 'link10')" onMouseOut="HideTip('tt10')" class=ISymbol>alureDestroyStream</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/alure-cpp.html#alureFreeDeviceNames" id=link11 onMouseOver="ShowTip(event, 'tt11', 'link11')" onMouseOut="HideTip('tt11')" class=ISymbol>alureFreeDeviceNames</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/alure-cpp.html#alureGetDeviceNames" id=link12 onMouseOver="ShowTip(event, 'tt12', 'link12')" onMouseOut="HideTip('tt12')" class=ISymbol>alureGetDeviceNames</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/alure-cpp.html#alureGetErrorString" id=link13 onMouseOver="ShowTip(event, 'tt13', 'link13')" onMouseOut="HideTip('tt13')" class=ISymbol>alureGetErrorString</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/alure-cpp.html#alureGetProcAddress" id=link14 onMouseOver="ShowTip(event, 'tt14', 'link14')" onMouseOut="HideTip('tt14')" class=ISymbol>alureGetProcAddress</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/alure-cpp.html#alureGetSampleFormat" id=link15 onMouseOver="ShowTip(event, 'tt15', 'link15')" onMouseOut="HideTip('tt15')" class=ISymbol>alureGetSampleFormat</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/stream-cpp.html#alureGetStreamFrequency" id=link16 onMouseOver="ShowTip(event, 'tt16', 'link16')" onMouseOut="HideTip('tt16')" class=ISymbol>alureGetStreamFrequency</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/stream-cpp.html#alureGetStreamLength" id=link17 onMouseOver="ShowTip(event, 'tt17', 'link17')" onMouseOut="HideTip('tt17')" class=ISymbol>alureGetStreamLength</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/alure-cpp.html#alureGetVersion" id=link18 onMouseOver="ShowTip(event, 'tt18', 'link18')" onMouseOut="HideTip('tt18')" class=ISymbol>alureGetVersion</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/alure-cpp.html#alureInitDevice" id=link19 onMouseOver="ShowTip(event, 'tt19', 'link19')" onMouseOut="HideTip('tt19')" class=ISymbol>alureInitDevice</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/alure-cpp.html#alureInstallDecodeCallbacks" id=link20 onMouseOver="ShowTip(event, 'tt20', 'link20')" onMouseOut="HideTip('tt20')" class=ISymbol>alureInstallDecodeCallbacks</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/streamplay-cpp.html#alurePauseSource" id=link21 onMouseOver="ShowTip(event, 'tt21', 'link21')" onMouseOut="HideTip('tt21')" class=ISymbol>alurePauseSource</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/streamplay-cpp.html#alurePlaySource" id=link22 onMouseOver="ShowTip(event, 'tt22', 'link22')" onMouseOut="HideTip('tt22')" class=ISymbol>alurePlaySource</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/streamplay-cpp.html#alurePlaySourceStream" id=link23 onMouseOver="ShowTip(event, 'tt23', 'link23')" onMouseOut="HideTip('tt23')" class=ISymbol>alurePlaySourceStream</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/streamplay-cpp.html#alureResumeSource" id=link24 onMouseOver="ShowTip(event, 'tt24', 'link24')" onMouseOut="HideTip('tt24')" class=ISymbol>alureResumeSource</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/stream-cpp.html#alureRewindStream" id=link25 onMouseOver="ShowTip(event, 'tt25', 'link25')" onMouseOut="HideTip('tt25')" class=ISymbol>alureRewindStream</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/istream-cpp.html#alureSetIOCallbacks" id=link26 onMouseOver="ShowTip(event, 'tt26', 'link26')" onMouseOut="HideTip('tt26')" class=ISymbol>alureSetIOCallbacks</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/stream-cpp.html#alureSetStreamOrder" id=link27 onMouseOver="ShowTip(event, 'tt27', 'link27')" onMouseOut="HideTip('tt27')" class=ISymbol>alureSetStreamOrder</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/stream-cpp.html#alureSetStreamPatchset" id=link28 onMouseOver="ShowTip(event, 'tt28', 'link28')" onMouseOut="HideTip('tt28')" class=ISymbol>alureSetStreamPatchset</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/alure-cpp.html#alureShutdownDevice" id=link29 onMouseOver="ShowTip(event, 'tt29', 'link29')" onMouseOut="HideTip('tt29')" class=ISymbol>alureShutdownDevice</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/alure-cpp.html#alureSleep" id=link30 onMouseOver="ShowTip(event, 'tt30', 'link30')" onMouseOut="HideTip('tt30')" class=ISymbol>alureSleep</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/streamplay-cpp.html#alureStopSource" id=link31 onMouseOver="ShowTip(event, 'tt31', 'link31')" onMouseOut="HideTip('tt31')" class=ISymbol>alureStopSource</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/stream-cpp.html#alureStreamSizeIsMicroSec" id=link32 onMouseOver="ShowTip(event, 'tt32', 'link32')" onMouseOut="HideTip('tt32')" class=ISymbol>alureStreamSizeIsMicroSec</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/streamplay-cpp.html#alureUpdate" id=link33 onMouseOver="ShowTip(event, 'tt33', 'link33')" onMouseOut="HideTip('tt33')" class=ISymbol>alureUpdate</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/streamplay-cpp.html#alureUpdateInterval" id=link34 onMouseOver="ShowTip(event, 'tt34', 'link34')" onMouseOut="HideTip('tt34')" class=ISymbol>alureUpdateInterval</a></td></tr><tr><td class=ISymbolPrefix id=ILastSymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/streamplay-cpp.html#Automatic_Playback"  class=ISymbol>Automatic Playback</a></td></tr><tr><td class=IHeading><a name="F"></a>F</td><td></td></tr><tr><td class=ISymbolPrefix id=IFirstSymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/istream-cpp.html#File_I/O"  class=ISymbol>File I/<wbr>O</a></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/buffer-cpp.html#File_Loading"  class=ISymbol>File Loading</a></td></tr><tr><td class=ISymbolPrefix id=ILastSymbolPrefix>&nbsp;</td><td class=IEntry><span class=ISymbol>Functions</span><div class=ISubIndex><a href="../files/alure-cpp.html#Functions"  class=IFile>alure.cpp</a><a href="../files/buffer-cpp.html#Functions"  class=IFile>buffer.cpp</a><a href="../files/istream-cpp.html#Functions"  class=IFile>istream.cpp</a><a href="../files/stream-cpp.html#Functions"  class=IFile>stream.cpp</a><a href="../files/streamplay-cpp.html#Functions"  class=IFile>streamplay.cpp</a></div></td></tr><tr><td class=IHeading><a name="M"></a>M</td><td></td></tr><tr><td class=ISymbolPrefix id=IOnlySymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/alure-cpp.html#Main_and_Miscellanious"  class=ISymbol>Main and Miscellanious</a></td></tr><tr><td class=IHeading><a name="S"></a>S</td><td></td></tr><tr><td class=ISymbolPrefix id=IOnlySymbolPrefix>&nbsp;</td><td class=IEntry><a href="../files/stream-cpp.html#Streaming"  class=ISymbol>Streaming</a></td></tr></table>
+<!--START_ND_TOOLTIPS-->
+<div class=CToolTip id="tt1"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters colspan=5>ALURE_API ALboolean ALURE_APIENTRY alureBufferDataFromFile(</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap>const&nbsp;</td><td class=PType nowrap>ALchar&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>fname,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>buffer</td></tr><tr><td class=PAfterParameters colspan=5>)</td></tr></table></td></tr></table></blockquote>Loads the given file into an existing OpenAL buffer object. </div></div><div class=CToolTip id="tt2"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters colspan=5>ALURE_API ALboolean ALURE_APIENTRY alureBufferDataFromMemory(</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap>const&nbsp;</td><td class=PType nowrap>ALubyte&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>fdata,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>length,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>buffer</td></tr><tr><td class=PAfterParameters colspan=5>)</td></tr></table></td></tr></table></blockquote>Loads a file image from memory into an existing OpenAL buffer object, similar to alureBufferDataFromFile. </div></div><div class=CToolTip id="tt3"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALsizei ALURE_APIENTRY alureBufferDataFromStream(</td><td class=PType nowrap>alureStream&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>stream,</td></tr><tr><td></td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap>numBufs,</td></tr><tr><td></td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>bufs</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Buffers the given buffer objects with the next chunks of data from the stream. </div></div><div class=CToolTip id="tt4"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALuint ALURE_APIENTRY alureCreateBufferFromFile(</td><td class=PTypePrefix nowrap>const&nbsp;</td><td class=PType nowrap>ALchar&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>fname</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Loads the given file into a new OpenAL buffer object. </div></div><div class=CToolTip id="tt5"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters colspan=5>ALURE_API ALuint ALURE_APIENTRY alureCreateBufferFromMemory(</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap>const&nbsp;</td><td class=PType nowrap>ALubyte&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>fdata,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>length</td></tr><tr><td class=PAfterParameters colspan=5>)</td></tr></table></td></tr></table></blockquote>Loads a file image from memory into a new OpenAL buffer object, similar to alureCreateBufferFromFile. </div></div><div class=CToolTip id="tt6"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters colspan=4>ALURE_API alureStream* ALURE_APIENTRY alureCreateStreamFromCallback(</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>(*callback)(void *userdata, ALubyte *data, ALuint bytes),</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>void&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>userdata,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALenum&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>format,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>samplerate,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>chunkLength,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>numBufs,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>bufs</td></tr><tr><td class=PAfterParameters colspan=4>)</td></tr></table></td></tr></table></blockquote>Creates a stream using the specified callback to retrieve data. </div></div><div class=CToolTip id="tt7"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters colspan=5>ALURE_API alureStream* ALURE_APIENTRY alureCreateStreamFromFile(</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap>const&nbsp;</td><td class=PType nowrap>ALchar&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>fname,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>chunkLength,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>numBufs,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>bufs</td></tr><tr><td class=PAfterParameters colspan=5>)</td></tr></table></td></tr></table></blockquote>Opens a file and sets it up for streaming. </div></div><div class=CToolTip id="tt8"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters colspan=5>ALURE_API alureStream* ALURE_APIENTRY alureCreateStreamFromMemory(</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap>const&nbsp;</td><td class=PType nowrap>ALubyte&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>fdata,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>length,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>chunkLength,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>numBufs,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>bufs</td></tr><tr><td class=PAfterParameters colspan=5>)</td></tr></table></td></tr></table></blockquote>Opens a file image from memory and sets it up for streaming, similar to alureCreateStreamFromFile. </div></div><div class=CToolTip id="tt9"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters colspan=5>ALURE_API alureStream* ALURE_APIENTRY alureCreateStreamFromStaticMemory(</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap>const&nbsp;</td><td class=PType nowrap>ALubyte&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>fdata,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>length,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>chunkLength,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>numBufs,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>bufs</td></tr><tr><td class=PAfterParameters colspan=5>)</td></tr></table></td></tr></table></blockquote>Identical to alureCreateStreamFromMemory, except the given memory is used directly and not duplicated. </div></div><div class=CToolTip id="tt10"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALboolean ALURE_APIENTRY alureDestroyStream(</td><td class=PType nowrap>alureStream&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>stream,</td></tr><tr><td></td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap>numBufs,</td></tr><tr><td></td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>bufs</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Closes an opened stream. </div></div><div class=CToolTip id="tt11"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALvoid ALURE_APIENTRY alureFreeDeviceNames(</td><td class=PTypePrefix nowrap>const&nbsp;</td><td class=PType nowrap>ALCchar&nbsp;</td><td class=PParameterPrefix nowrap>**</td><td class=PParameter nowrap>names</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Frees the device name array returned from alureGetDeviceNames.</div></div><div class=CToolTip id="tt12"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API const ALCchar** ALURE_APIENTRY alureGetDeviceNames(</td><td class=PType nowrap>ALCboolean&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap>all,</td></tr><tr><td></td><td class=PType nowrap>ALCsizei&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>count</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Gets an array of device name strings from OpenAL. </div></div><div class=CToolTip id="tt13"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API const ALchar* ALURE_APIENTRY alureGetErrorString(</td><td class=PParameter nowrap>void</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Returns a string describing the last error encountered.</div></div><div class=CToolTip id="tt14"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API void* ALURE_APIENTRY alureGetProcAddress(</td><td class=PTypePrefix nowrap>const&nbsp;</td><td class=PType nowrap>ALchar&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>funcname</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Returns a pointer for the named ALURE function.</div></div><div class=CToolTip id="tt15"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALenum ALURE_APIENTRY alureGetSampleFormat(</td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameter nowrap>channels,</td></tr><tr><td></td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameter nowrap>bits,</td></tr><tr><td></td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameter nowrap>floatbits</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Retrieves an OpenAL format for the given sample format. </div></div><div class=CToolTip id="tt16"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALsizei ALURE_APIENTRY alureGetStreamFrequency(</td><td class=PType nowrap>alureStream&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>stream</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Retrieves the frequency used by the given stream.</div></div><div class=CToolTip id="tt17"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API alureInt64 ALURE_APIENTRY alureGetStreamLength(</td><td class=PType nowrap>alureStream&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>stream</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Retrieves an approximate number of samples for the stream. </div></div><div class=CToolTip id="tt18"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API void ALURE_APIENTRY alureGetVersion(</td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>major,</td></tr><tr><td></td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>minor</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Stores the major and minor version of the library. </div></div><div class=CToolTip id="tt19"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALboolean ALURE_APIENTRY alureInitDevice(</td><td class=PTypePrefix nowrap>const&nbsp;</td><td class=PType nowrap>ALCchar&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>name,</td></tr><tr><td></td><td class=PTypePrefix nowrap>const&nbsp;</td><td class=PType nowrap>ALCint&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>attribs</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Opens the named device, creates a context with the given attributes, and sets that context as current. </div></div><div class=CToolTip id="tt20"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters colspan=4>ALURE_API ALboolean ALURE_APIENTRY alureInstallDecodeCallbacks(</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALint&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>index,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>void&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>(*open_file)(const ALchar *filename),</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>void&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>(*open_memory)(const ALubyte *data, ALuint length),</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALboolean&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>(*get_format)(void *instance, ALenum *format, ALuint *samplerate, ALuint *blocksize),</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>(*decode)(void *instance, ALubyte *data, ALuint bytes),</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALboolean&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>(*rewind)(void *instance),</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>void&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>(*close)(void *instance)</td></tr><tr><td class=PAfterParameters colspan=4>)</td></tr></table></td></tr></table></blockquote>Installs callbacks to enable ALURE to handle more file types. </div></div><div class=CToolTip id="tt21"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALboolean ALURE_APIENTRY alurePauseSource(</td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameter nowrap>source</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Pauses the specified source ID, and any associated stream. </div></div><div class=CToolTip id="tt22"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters colspan=4>ALURE_API ALboolean ALURE_APIENTRY alurePlaySource(</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>source,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>void&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>(*callback)(void *userdata, ALuint source),</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>void&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>userdata</td></tr><tr><td class=PAfterParameters colspan=4>)</td></tr></table></td></tr></table></blockquote>Plays the specified source ID and watches for it to stop. </div></div><div class=CToolTip id="tt23"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters colspan=4>ALURE_API ALboolean ALURE_APIENTRY alurePlaySourceStream(</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>source,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>alureStream&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>stream,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>numBufs,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>loopcount,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>void&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>(*eos_callback)(void *userdata, ALuint source),</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>void&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>userdata</td></tr><tr><td class=PAfterParameters colspan=4>)</td></tr></table></td></tr></table></blockquote>Starts playing a stream, using the specified source ID. </div></div><div class=CToolTip id="tt24"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALboolean ALURE_APIENTRY alureResumeSource(</td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameter nowrap>source</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Resumes the specified source ID after being paused.</div></div><div class=CToolTip id="tt25"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALboolean ALURE_APIENTRY alureRewindStream(</td><td class=PType nowrap>alureStream&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>stream</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Rewinds the stream so that the next alureBufferDataFromStream call will restart from the beginning of the audio file.</div></div><div class=CToolTip id="tt26"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters colspan=4>ALURE_API ALboolean ALURE_APIENTRY alureSetIOCallbacks(</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>void&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>(*open)(const char *filename, ALuint mode),</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>void&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>(*close)(void *handle),</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>(*read)(void *handle, ALubyte *buf, ALuint bytes),</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>ALsizei&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>(*write)(void *handle, const ALubyte *buf, ALuint bytes),</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PType nowrap>alureInt64&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap width=100%>(*seek)(void *handle, alureInt64 offset, int whence)</td></tr><tr><td class=PAfterParameters colspan=4>)</td></tr></table></td></tr></table></blockquote>Provides callbacks for alternative methods to handle file I/O. </div></div><div class=CToolTip id="tt27"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALboolean ALURE_APIENTRY alureSetStreamOrder(</td><td class=PType nowrap>alureStream&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap>stream,</td></tr><tr><td></td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameterPrefix nowrap></td><td class=PParameter nowrap>order</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Skips the module decoder to the specified order, so following buffering calls will decode from the specified order. </div></div><div class=CToolTip id="tt28"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters colspan=5>ALURE_API ALboolean ALURE_APIENTRY alureSetStreamPatchset(</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap></td><td class=PType nowrap>alureStream&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>stream,</td></tr><tr><td>&nbsp;&nbsp;&nbsp;</td><td class=PTypePrefix nowrap>const&nbsp;</td><td class=PType nowrap>ALchar&nbsp;</td><td class=PParameterPrefix nowrap>*</td><td class=PParameter nowrap width=100%>patchset</td></tr><tr><td class=PAfterParameters colspan=5>)</td></tr></table></td></tr></table></blockquote>Specifies the patchset to use for MIDI streams. </div></div><div class=CToolTip id="tt29"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALboolean ALURE_APIENTRY alureShutdownDevice(</td><td class=PParameter nowrap>void</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Destroys the current context and closes its associated device.</div></div><div class=CToolTip id="tt30"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALboolean ALURE_APIENTRY alureSleep(</td><td class=PType nowrap>ALfloat&nbsp;</td><td class=PParameter nowrap>duration</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Rests the calling thread for the given number of seconds.</div></div><div class=CToolTip id="tt31"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALboolean ALURE_APIENTRY alureStopSource(</td><td class=PType nowrap>ALuint&nbsp;</td><td class=PParameter nowrap>source,</td></tr><tr><td></td><td class=PType nowrap>ALboolean&nbsp;</td><td class=PParameter nowrap>run_callback</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Stops the specified source ID, and any associated stream. </div></div><div class=CToolTip id="tt32"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALboolean ALURE_APIENTRY alureStreamSizeIsMicroSec(</td><td class=PType nowrap>ALboolean&nbsp;</td><td class=PParameter nowrap>useUS</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Specifies if the chunk size value given to the alureCreateStream functions is in bytes (default) or microseconds. </div></div><div class=CToolTip id="tt33"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API void ALURE_APIENTRY alureUpdate(</td><td class=PParameter nowrap>void</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Updates the running list of streams, and checks for stopped sources. </div></div><div class=CToolTip id="tt34"><div class=CFunction><blockquote><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters nowrap>ALURE_API ALboolean ALURE_APIENTRY alureUpdateInterval(</td><td class=PType nowrap>ALfloat&nbsp;</td><td class=PParameter nowrap>interval</td><td class=PAfterParameters nowrap>)</td></tr></table></td></tr></table></blockquote>Sets up a timer or thread to automatically call alureUpdate at the given interval, in seconds. </div></div><!--END_ND_TOOLTIPS-->
+
+
+<!--START_ND_TOOLTIPS-->
+<!--END_ND_TOOLTIPS-->
+
+
+<!--START_ND_TOOLTIPS-->
+<!--END_ND_TOOLTIPS-->
+
+
+<!--START_ND_TOOLTIPS-->
+<!--END_ND_TOOLTIPS-->
+
+</div><!--Index-->
+
+
+<div id=Footer><a href="http://www.naturaldocs.org">Generated by Natural Docs</a></div><!--Footer-->
+
+
+<div id=Menu><div class=MTitle>ALURE<div class=MSubTitle>API Reference</div></div><div class=MEntry><div class=MFile><a href="../files/alure-cpp.html">Main and Miscellanious</a></div></div><div class=MEntry><div class=MFile><a href="../files/buffer-cpp.html">File Loading</a></div></div><div class=MEntry><div class=MFile><a href="../files/stream-cpp.html">Streaming</a></div></div><div class=MEntry><div class=MFile><a href="../files/istream-cpp.html">File I/<wbr>O</a></div></div><div class=MEntry><div class=MFile><a href="../files/streamplay-cpp.html">Automatic Playback</a></div></div><div class=MEntry><div class=MGroup><a href="javascript:ToggleMenu('MGroupContent1')">Index</a><div class=MGroupContent id=MGroupContent1><div class=MEntry><div class=MIndex id=MSelected>Everything</div></div><div class=MEntry><div class=MIndex><a href="Functions.html">Functions</a></div></div></div></div></div><script type="text/javascript"><!--
+var searchPanel = new SearchPanel("searchPanel", "HTML", "../search");
+--></script><div id=MSearchPanel class=MSearchPanelInactive><input type=text id=MSearchField value=Search onFocus="searchPanel.OnSearchFieldFocus(true)" onBlur="searchPanel.OnSearchFieldFocus(false)" onKeyUp="searchPanel.OnSearchFieldChange()"><select id=MSearchType onFocus="searchPanel.OnSearchTypeFocus(true)" onBlur="searchPanel.OnSearchTypeFocus(false)" onChange="searchPanel.OnSearchTypeChange()"><option  id=MSearchEverything selected value="General">Everything</option><option value="Functions">Functions</option></select></div></div><!--Menu-->
+
+
+<div id=MSearchResultsWindow><iframe src="" frameborder=0 name=MSearchResults id=MSearchResults></iframe><a href="javascript:searchPanel.CloseResultsWindow()" id=MSearchResultsWindowClose>Close</a></div>
+
+
+<script language=JavaScript><!--
+if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
\ No newline at end of file
diff --git a/docs/html/javascript/main.js b/docs/html/javascript/main.js
new file mode 100644 (file)
index 0000000..efcdca9
--- /dev/null
@@ -0,0 +1,836 @@
+// This file is part of Natural Docs, which is Copyright (C) 2003-2008 Greg Valure\r
+// Natural Docs is licensed under the GPL\r
+\r
+\r
+//\r
+//  Browser Styles\r
+// ____________________________________________________________________________\r
+\r
+var agt=navigator.userAgent.toLowerCase();\r
+var browserType;\r
+var browserVer;\r
+\r
+if (agt.indexOf("opera") != -1)\r
+    {\r
+    browserType = "Opera";\r
+\r
+    if (agt.indexOf("opera 7") != -1 || agt.indexOf("opera/7") != -1)\r
+        {  browserVer = "Opera7";  }\r
+    else if (agt.indexOf("opera 8") != -1 || agt.indexOf("opera/8") != -1)\r
+        {  browserVer = "Opera8";  }\r
+    else if (agt.indexOf("opera 9") != -1 || agt.indexOf("opera/9") != -1)\r
+        {  browserVer = "Opera9";  }\r
+    }\r
+\r
+else if (agt.indexOf("applewebkit") != -1)\r
+    {\r
+    browserType = "Safari";\r
+\r
+    if (agt.indexOf("version/3") != -1)\r
+        {  browserVer = "Safari3";  }\r
+    else if (agt.indexOf("safari/4") != -1)\r
+        {  browserVer = "Safari2";  }\r
+    }\r
+\r
+else if (agt.indexOf("khtml") != -1)\r
+    {\r
+    browserType = "Konqueror";\r
+    }\r
+\r
+else if (agt.indexOf("msie") != -1)\r
+    {\r
+    browserType = "IE";\r
+\r
+    if (agt.indexOf("msie 6") != -1)\r
+        {  browserVer = "IE6";  }\r
+    else if (agt.indexOf("msie 7") != -1)\r
+        {  browserVer = "IE7";  }\r
+    }\r
+\r
+else if (agt.indexOf("gecko") != -1)\r
+    {\r
+    browserType = "Firefox";\r
+\r
+    if (agt.indexOf("rv:1.7") != -1)\r
+        {  browserVer = "Firefox1";  }\r
+    else if (agt.indexOf("rv:1.8)") != -1 || agt.indexOf("rv:1.8.0") != -1)\r
+        {  browserVer = "Firefox15";  }\r
+    else if (agt.indexOf("rv:1.8.1") != -1)\r
+        {  browserVer = "Firefox2";  }\r
+    }\r
+\r
+\r
+//\r
+//  Support Functions\r
+// ____________________________________________________________________________\r
+\r
+\r
+function GetXPosition(item)\r
+    {\r
+    var position = 0;\r
+\r
+    if (item.offsetWidth != null)\r
+        {\r
+        while (item != document.body && item != null)\r
+            {\r
+            position += item.offsetLeft;\r
+            item = item.offsetParent;\r
+            };\r
+        };\r
+\r
+    return position;\r
+    };\r
+\r
+\r
+function GetYPosition(item)\r
+    {\r
+    var position = 0;\r
+\r
+    if (item.offsetWidth != null)\r
+        {\r
+        while (item != document.body && item != null)\r
+            {\r
+            position += item.offsetTop;\r
+            item = item.offsetParent;\r
+            };\r
+        };\r
+\r
+    return position;\r
+    };\r
+\r
+\r
+function MoveToPosition(item, x, y)\r
+    {\r
+    // Opera 5 chokes on the px extension, so it can use the Microsoft one instead.\r
+\r
+    if (item.style.left != null)\r
+        {\r
+        item.style.left = x + "px";\r
+        item.style.top = y + "px";\r
+        }\r
+    else if (item.style.pixelLeft != null)\r
+        {\r
+        item.style.pixelLeft = x;\r
+        item.style.pixelTop = y;\r
+        };\r
+    };\r
+\r
+\r
+//\r
+//  Menu\r
+// ____________________________________________________________________________\r
+\r
+\r
+function ToggleMenu(id)\r
+    {\r
+    if (!window.document.getElementById)\r
+        {  return;  };\r
+\r
+    var display = window.document.getElementById(id).style.display;\r
+\r
+    if (display == "none")\r
+        {  display = "block";  }\r
+    else\r
+        {  display = "none";  }\r
+\r
+    window.document.getElementById(id).style.display = display;\r
+    }\r
+\r
+function HideAllBut(ids, max)\r
+    {\r
+    if (document.getElementById)\r
+        {\r
+        ids.sort( function(a,b) { return a - b; } );\r
+        var number = 1;\r
+\r
+        while (number < max)\r
+            {\r
+            if (ids.length > 0 && number == ids[0])\r
+                {  ids.shift();  }\r
+            else\r
+                {\r
+                document.getElementById("MGroupContent" + number).style.display = "none";\r
+                };\r
+\r
+            number++;\r
+            };\r
+        };\r
+    }\r
+\r
+\r
+//\r
+//  Tooltips\r
+// ____________________________________________________________________________\r
+\r
+\r
+var tooltipTimer = 0;\r
+\r
+function ShowTip(event, tooltipID, linkID)\r
+    {\r
+    if (tooltipTimer)\r
+        {  clearTimeout(tooltipTimer);  };\r
+\r
+    var docX = event.clientX + window.pageXOffset;\r
+    var docY = event.clientY + window.pageYOffset;\r
+\r
+    var showCommand = "ReallyShowTip('" + tooltipID + "', '" + linkID + "', " + docX + ", " + docY + ")";\r
+\r
+    tooltipTimer = setTimeout(showCommand, 1000);\r
+    }\r
+\r
+function ReallyShowTip(tooltipID, linkID, docX, docY)\r
+    {\r
+    tooltipTimer = 0;\r
+\r
+    var tooltip;\r
+    var link;\r
+\r
+    if (document.getElementById)\r
+        {\r
+        tooltip = document.getElementById(tooltipID);\r
+        link = document.getElementById(linkID);\r
+        }\r
+/*    else if (document.all)\r
+        {\r
+        tooltip = eval("document.all['" + tooltipID + "']");\r
+        link = eval("document.all['" + linkID + "']");\r
+        }\r
+*/\r
+    if (tooltip)\r
+        {\r
+        var left = GetXPosition(link);\r
+        var top = GetYPosition(link);\r
+        top += link.offsetHeight;\r
+\r
+\r
+        // The fallback method is to use the mouse X and Y relative to the document.  We use a separate if and test if its a number\r
+        // in case some browser snuck through the above if statement but didn't support everything.\r
+\r
+        if (!isFinite(top) || top == 0)\r
+            {\r
+            left = docX;\r
+            top = docY;\r
+            }\r
+\r
+        // Some spacing to get it out from under the cursor.\r
+\r
+        top += 10;\r
+\r
+        // Make sure the tooltip doesnt get smushed by being too close to the edge, or in some browsers, go off the edge of the\r
+        // page.  We do it here because Konqueror does get offsetWidth right even if it doesnt get the positioning right.\r
+\r
+        if (tooltip.offsetWidth != null)\r
+            {\r
+            var width = tooltip.offsetWidth;\r
+            var docWidth = document.body.clientWidth;\r
+\r
+            if (left + width > docWidth)\r
+                {  left = docWidth - width - 1;  }\r
+\r
+            // If there's a horizontal scroll bar we could go past zero because it's using the page width, not the window width.\r
+            if (left < 0)\r
+                {  left = 0;  };\r
+            }\r
+\r
+        MoveToPosition(tooltip, left, top);\r
+        tooltip.style.visibility = "visible";\r
+        }\r
+    }\r
+\r
+function HideTip(tooltipID)\r
+    {\r
+    if (tooltipTimer)\r
+        {\r
+        clearTimeout(tooltipTimer);\r
+        tooltipTimer = 0;\r
+        }\r
+\r
+    var tooltip;\r
+\r
+    if (document.getElementById)\r
+        {  tooltip = document.getElementById(tooltipID); }\r
+    else if (document.all)\r
+        {  tooltip = eval("document.all['" + tooltipID + "']");  }\r
+\r
+    if (tooltip)\r
+        {  tooltip.style.visibility = "hidden";  }\r
+    }\r
+\r
+\r
+//\r
+//  Blockquote fix for IE\r
+// ____________________________________________________________________________\r
+\r
+\r
+function NDOnLoad()\r
+    {\r
+    if (browserVer == "IE6")\r
+        {\r
+        var scrollboxes = document.getElementsByTagName('blockquote');\r
+\r
+        if (scrollboxes.item(0))\r
+            {\r
+            NDDoResize();\r
+            window.onresize=NDOnResize;\r
+            };\r
+        };\r
+    };\r
+\r
+\r
+var resizeTimer = 0;\r
+\r
+function NDOnResize()\r
+    {\r
+    if (resizeTimer != 0)\r
+        {  clearTimeout(resizeTimer);  };\r
+\r
+    resizeTimer = setTimeout(NDDoResize, 250);\r
+    };\r
+\r
+\r
+function NDDoResize()\r
+    {\r
+    var scrollboxes = document.getElementsByTagName('blockquote');\r
+\r
+    var i;\r
+    var item;\r
+\r
+    i = 0;\r
+    while (item = scrollboxes.item(i))\r
+        {\r
+        item.style.width = 100;\r
+        i++;\r
+        };\r
+\r
+    i = 0;\r
+    while (item = scrollboxes.item(i))\r
+        {\r
+        item.style.width = item.parentNode.offsetWidth;\r
+        i++;\r
+        };\r
+\r
+    clearTimeout(resizeTimer);\r
+    resizeTimer = 0;\r
+    }\r
+\r
+\r
+\r
+/* ________________________________________________________________________________________________________\r
+\r
+    Class: SearchPanel\r
+    ________________________________________________________________________________________________________\r
+\r
+    A class handling everything associated with the search panel.\r
+\r
+    Parameters:\r
+\r
+        name - The name of the global variable that will be storing this instance.  Is needed to be able to set timeouts.\r
+        mode - The mode the search is going to work in.  Pass <NaturalDocs::Builder::Base->CommandLineOption()>, so the\r
+                   value will be something like "HTML" or "FramedHTML".\r
+\r
+    ________________________________________________________________________________________________________\r
+*/\r
+\r
+\r
+function SearchPanel(name, mode, resultsPath)\r
+    {\r
+    if (!name || !mode || !resultsPath)\r
+        {  alert("Incorrect parameters to SearchPanel.");  };\r
+\r
+\r
+    // Group: Variables\r
+    // ________________________________________________________________________\r
+\r
+    /*\r
+        var: name\r
+        The name of the global variable that will be storing this instance of the class.\r
+    */\r
+    this.name = name;\r
+\r
+    /*\r
+        var: mode\r
+        The mode the search is going to work in, such as "HTML" or "FramedHTML".\r
+    */\r
+    this.mode = mode;\r
+\r
+    /*\r
+        var: resultsPath\r
+        The relative path from the current HTML page to the results page directory.\r
+    */\r
+    this.resultsPath = resultsPath;\r
+\r
+    /*\r
+        var: keyTimeout\r
+        The timeout used between a keystroke and when a search is performed.\r
+    */\r
+    this.keyTimeout = 0;\r
+\r
+    /*\r
+        var: keyTimeoutLength\r
+        The length of <keyTimeout> in thousandths of a second.\r
+    */\r
+    this.keyTimeoutLength = 500;\r
+\r
+    /*\r
+        var: lastSearchValue\r
+        The last search string executed, or an empty string if none.\r
+    */\r
+    this.lastSearchValue = "";\r
+\r
+    /*\r
+        var: lastResultsPage\r
+        The last results page.  The value is only relevant if <lastSearchValue> is set.\r
+    */\r
+    this.lastResultsPage = "";\r
+\r
+    /*\r
+        var: deactivateTimeout\r
+\r
+        The timeout used between when a control is deactivated and when the entire panel is deactivated.  Is necessary\r
+        because a control may be deactivated in favor of another control in the same panel, in which case it should stay\r
+        active.\r
+    */\r
+    this.deactivateTimout = 0;\r
+\r
+    /*\r
+        var: deactivateTimeoutLength\r
+        The length of <deactivateTimeout> in thousandths of a second.\r
+    */\r
+    this.deactivateTimeoutLength = 200;\r
+\r
+\r
+\r
+\r
+    // Group: DOM Elements\r
+    // ________________________________________________________________________\r
+\r
+\r
+    // Function: DOMSearchField\r
+    this.DOMSearchField = function()\r
+        {  return document.getElementById("MSearchField");  };\r
+\r
+    // Function: DOMSearchType\r
+    this.DOMSearchType = function()\r
+        {  return document.getElementById("MSearchType");  };\r
+\r
+    // Function: DOMPopupSearchResults\r
+    this.DOMPopupSearchResults = function()\r
+        {  return document.getElementById("MSearchResults");  };\r
+\r
+    // Function: DOMPopupSearchResultsWindow\r
+    this.DOMPopupSearchResultsWindow = function()\r
+        {  return document.getElementById("MSearchResultsWindow");  };\r
+\r
+    // Function: DOMSearchPanel\r
+    this.DOMSearchPanel = function()\r
+        {  return document.getElementById("MSearchPanel");  };\r
+\r
+\r
+\r
+\r
+    // Group: Event Handlers\r
+    // ________________________________________________________________________\r
+\r
+\r
+    /*\r
+        Function: OnSearchFieldFocus\r
+        Called when focus is added or removed from the search field.\r
+    */\r
+    this.OnSearchFieldFocus = function(isActive)\r
+        {\r
+        this.Activate(isActive);\r
+        };\r
+\r
+\r
+    /*\r
+        Function: OnSearchFieldChange\r
+        Called when the content of the search field is changed.\r
+    */\r
+    this.OnSearchFieldChange = function()\r
+        {\r
+        if (this.keyTimeout)\r
+            {\r
+            clearTimeout(this.keyTimeout);\r
+            this.keyTimeout = 0;\r
+            };\r
+\r
+        var searchValue = this.DOMSearchField().value.replace(/ +/g, "");\r
+\r
+        if (searchValue != this.lastSearchValue)\r
+            {\r
+            if (searchValue != "")\r
+                {\r
+                this.keyTimeout = setTimeout(this.name + ".Search()", this.keyTimeoutLength);\r
+                }\r
+            else\r
+                {\r
+                if (this.mode == "HTML")\r
+                    {  this.DOMPopupSearchResultsWindow().style.display = "none";  };\r
+                this.lastSearchValue = "";\r
+                };\r
+            };\r
+        };\r
+\r
+\r
+    /*\r
+        Function: OnSearchTypeFocus\r
+        Called when focus is added or removed from the search type.\r
+    */\r
+    this.OnSearchTypeFocus = function(isActive)\r
+        {\r
+        this.Activate(isActive);\r
+        };\r
+\r
+\r
+    /*\r
+        Function: OnSearchTypeChange\r
+        Called when the search type is changed.\r
+    */\r
+    this.OnSearchTypeChange = function()\r
+        {\r
+        var searchValue = this.DOMSearchField().value.replace(/ +/g, "");\r
+\r
+        if (searchValue != "")\r
+            {\r
+            this.Search();\r
+            };\r
+        };\r
+\r
+\r
+\r
+    // Group: Action Functions\r
+    // ________________________________________________________________________\r
+\r
+\r
+    /*\r
+        Function: CloseResultsWindow\r
+        Closes the results window.\r
+    */\r
+    this.CloseResultsWindow = function()\r
+        {\r
+        this.DOMPopupSearchResultsWindow().style.display = "none";\r
+        this.Activate(false, true);\r
+        };\r
+\r
+\r
+    /*\r
+        Function: Search\r
+        Performs a search.\r
+    */\r
+    this.Search = function()\r
+        {\r
+        this.keyTimeout = 0;\r
+\r
+        var searchValue = this.DOMSearchField().value.replace(/^ +/, "");\r
+        var searchTopic = this.DOMSearchType().value;\r
+\r
+        var pageExtension = searchValue.substr(0,1);\r
+\r
+        if (pageExtension.match(/^[a-z]/i))\r
+            {  pageExtension = pageExtension.toUpperCase();  }\r
+        else if (pageExtension.match(/^[0-9]/))\r
+            {  pageExtension = 'Numbers';  }\r
+        else\r
+            {  pageExtension = "Symbols";  };\r
+\r
+        var resultsPage;\r
+        var resultsPageWithSearch;\r
+        var hasResultsPage;\r
+\r
+        // indexSectionsWithContent is defined in searchdata.js\r
+        if (indexSectionsWithContent[searchTopic][pageExtension] == true)\r
+            {\r
+            resultsPage = this.resultsPath + '/' + searchTopic + pageExtension + '.html';\r
+            resultsPageWithSearch = resultsPage+'?'+escape(searchValue);\r
+            hasResultsPage = true;\r
+            }\r
+        else\r
+            {\r
+            resultsPage = this.resultsPath + '/NoResults.html';\r
+            resultsPageWithSearch = resultsPage;\r
+            hasResultsPage = false;\r
+            };\r
+\r
+        var resultsFrame;\r
+        if (this.mode == "HTML")\r
+            {  resultsFrame = window.frames.MSearchResults;  }\r
+        else if (this.mode == "FramedHTML")\r
+            {  resultsFrame = window.top.frames['Content'];  };\r
+\r
+\r
+        if (resultsPage != this.lastResultsPage ||\r
+\r
+            // Bug in IE.  If everything becomes hidden in a run, none of them will be able to be reshown in the next for some\r
+            // reason.  It counts the right number of results, and you can even read the display as "block" after setting it, but it\r
+            // just doesn't work in IE 6 or IE 7.  So if we're on the right page but the previous search had no results, reload the\r
+            // page anyway to get around the bug.\r
+            (browserType == "IE" && hasResultsPage &&\r
+               (!resultsFrame.searchResults || resultsFrame.searchResults.lastMatchCount == 0)) )\r
+\r
+            {\r
+            resultsFrame.location.href = resultsPageWithSearch;\r
+            }\r
+\r
+        // So if the results page is right and there's no IE bug, reperform the search on the existing page.  We have to check if there\r
+        // are results because NoResults.html doesn't have any JavaScript, and it would be useless to do anything on that page even\r
+        // if it did.\r
+        else if (hasResultsPage)\r
+            {\r
+            // We need to check if this exists in case the frame is present but didn't finish loading.\r
+            if (resultsFrame.searchResults)\r
+                {  resultsFrame.searchResults.Search(searchValue);  }\r
+\r
+            // Otherwise just reload instead of waiting.\r
+            else\r
+                {  resultsFrame.location.href = resultsPageWithSearch;  };\r
+            };\r
+\r
+\r
+        var domPopupSearchResultsWindow = this.DOMPopupSearchResultsWindow();\r
+\r
+        if (this.mode == "HTML" && domPopupSearchResultsWindow.style.display != "block")\r
+            {\r
+            var domSearchType = this.DOMSearchType();\r
+\r
+            var left = GetXPosition(domSearchType);\r
+            var top = GetYPosition(domSearchType) + domSearchType.offsetHeight;\r
+\r
+            MoveToPosition(domPopupSearchResultsWindow, left, top);\r
+            domPopupSearchResultsWindow.style.display = 'block';\r
+            };\r
+\r
+\r
+        this.lastSearchValue = searchValue;\r
+        this.lastResultsPage = resultsPage;\r
+        };\r
+\r
+\r
+\r
+    // Group: Activation Functions\r
+    // Functions that handle whether the entire panel is active or not.\r
+    // ________________________________________________________________________\r
+\r
+\r
+    /*\r
+        Function: Activate\r
+\r
+        Activates or deactivates the search panel, resetting things to their default values if necessary.  You can call this on every\r
+        control's OnBlur() and it will handle not deactivating the entire panel when focus is just switching between them transparently.\r
+\r
+        Parameters:\r
+\r
+            isActive - Whether you're activating or deactivating the panel.\r
+            ignoreDeactivateDelay - Set if you're positive the action will deactivate the panel and thus want to skip the delay.\r
+    */\r
+    this.Activate = function(isActive, ignoreDeactivateDelay)\r
+        {\r
+        // We want to ignore isActive being false while the results window is open.\r
+        if (isActive || (this.mode == "HTML" && this.DOMPopupSearchResultsWindow().style.display == "block"))\r
+            {\r
+            if (this.inactivateTimeout)\r
+                {\r
+                clearTimeout(this.inactivateTimeout);\r
+                this.inactivateTimeout = 0;\r
+                };\r
+\r
+            this.DOMSearchPanel().className = 'MSearchPanelActive';\r
+\r
+            var searchField = this.DOMSearchField();\r
+\r
+            if (searchField.value == 'Search')\r
+                 {  searchField.value = "";  }\r
+            }\r
+        else if (!ignoreDeactivateDelay)\r
+            {\r
+            this.inactivateTimeout = setTimeout(this.name + ".InactivateAfterTimeout()", this.inactivateTimeoutLength);\r
+            }\r
+        else\r
+            {\r
+            this.InactivateAfterTimeout();\r
+            };\r
+        };\r
+\r
+\r
+    /*\r
+        Function: InactivateAfterTimeout\r
+\r
+        Called by <inactivateTimeout>, which is set by <Activate()>.  Inactivation occurs on a timeout because a control may\r
+        receive OnBlur() when focus is really transferring to another control in the search panel.  In this case we don't want to\r
+        actually deactivate the panel because not only would that cause a visible flicker but it could also reset the search value.\r
+        So by doing it on a timeout instead, there's a short period where the second control's OnFocus() can cancel the deactivation.\r
+    */\r
+    this.InactivateAfterTimeout = function()\r
+        {\r
+        this.inactivateTimeout = 0;\r
+\r
+        this.DOMSearchPanel().className = 'MSearchPanelInactive';\r
+        this.DOMSearchField().value = "Search";\r
+\r
+           this.lastSearchValue = "";\r
+           this.lastResultsPage = "";\r
+        };\r
+    };\r
+\r
+\r
+\r
+\r
+/* ________________________________________________________________________________________________________\r
+\r
+   Class: SearchResults\r
+   _________________________________________________________________________________________________________\r
+\r
+   The class that handles everything on the search results page.\r
+   _________________________________________________________________________________________________________\r
+*/\r
+\r
+\r
+function SearchResults(name, mode)\r
+    {\r
+    /*\r
+        var: mode\r
+        The mode the search is going to work in, such as "HTML" or "FramedHTML".\r
+    */\r
+    this.mode = mode;\r
+\r
+    /*\r
+        var: lastMatchCount\r
+        The number of matches from the last run of <Search()>.\r
+    */\r
+    this.lastMatchCount = 0;\r
+\r
+\r
+    /*\r
+        Function: Toggle\r
+        Toggles the visibility of the passed element ID.\r
+    */\r
+    this.Toggle = function(id)\r
+        {\r
+        if (this.mode == "FramedHTML")\r
+            {  return;  };\r
+\r
+        var parentElement = document.getElementById(id);\r
+\r
+        var element = parentElement.firstChild;\r
+\r
+        while (element && element != parentElement)\r
+            {\r
+            if (element.nodeName == 'DIV' && element.className == 'ISubIndex')\r
+                {\r
+                if (element.style.display == 'block')\r
+                    {  element.style.display = "none";  }\r
+                else\r
+                    {  element.style.display = 'block';  }\r
+                };\r
+\r
+            if (element.nodeName == 'DIV' && element.hasChildNodes())\r
+                {  element = element.firstChild;  }\r
+            else if (element.nextSibling)\r
+                {  element = element.nextSibling;  }\r
+            else\r
+                {\r
+                do\r
+                    {\r
+                    element = element.parentNode;\r
+                    }\r
+                while (element && element != parentElement && !element.nextSibling);\r
+\r
+                if (element && element != parentElement)\r
+                    {  element = element.nextSibling;  };\r
+                };\r
+            };\r
+        };\r
+\r
+\r
+    /*\r
+        Function: Search\r
+\r
+        Searches for the passed string.  If there is no parameter, it takes it from the URL query.\r
+\r
+        Always returns true, since other documents may try to call it and that may or may not be possible.\r
+    */\r
+    this.Search = function(search)\r
+        {\r
+        if (!search)\r
+            {\r
+            search = window.location.search;\r
+            search = search.substring(1);  // Remove the leading ?\r
+            search = unescape(search);\r
+            };\r
+\r
+        search = search.replace(/^ +/, "");\r
+        search = search.replace(/ +$/, "");\r
+        search = search.toLowerCase();\r
+\r
+        if (search.match(/[^a-z0-9]/)) // Just a little speedup so it doesn't have to go through the below unnecessarily.\r
+            {\r
+            search = search.replace(/\_/g, "_und");\r
+            search = search.replace(/\ +/gi, "_spc");\r
+            search = search.replace(/\~/g, "_til");\r
+            search = search.replace(/\!/g, "_exc");\r
+            search = search.replace(/\@/g, "_att");\r
+            search = search.replace(/\#/g, "_num");\r
+            search = search.replace(/\$/g, "_dol");\r
+            search = search.replace(/\%/g, "_pct");\r
+            search = search.replace(/\^/g, "_car");\r
+            search = search.replace(/\&/g, "_amp");\r
+            search = search.replace(/\*/g, "_ast");\r
+            search = search.replace(/\(/g, "_lpa");\r
+            search = search.replace(/\)/g, "_rpa");\r
+            search = search.replace(/\-/g, "_min");\r
+            search = search.replace(/\+/g, "_plu");\r
+            search = search.replace(/\=/g, "_equ");\r
+            search = search.replace(/\{/g, "_lbc");\r
+            search = search.replace(/\}/g, "_rbc");\r
+            search = search.replace(/\[/g, "_lbk");\r
+            search = search.replace(/\]/g, "_rbk");\r
+            search = search.replace(/\:/g, "_col");\r
+            search = search.replace(/\;/g, "_sco");\r
+            search = search.replace(/\"/g, "_quo");\r
+            search = search.replace(/\'/g, "_apo");\r
+            search = search.replace(/\</g, "_lan");\r
+            search = search.replace(/\>/g, "_ran");\r
+            search = search.replace(/\,/g, "_com");\r
+            search = search.replace(/\./g, "_per");\r
+            search = search.replace(/\?/g, "_que");\r
+            search = search.replace(/\//g, "_sla");\r
+            search = search.replace(/[^a-z0-9\_]i/gi, "_zzz");\r
+            };\r
+\r
+        var resultRows = document.getElementsByTagName("div");\r
+        var matches = 0;\r
+\r
+        var i = 0;\r
+        while (i < resultRows.length)\r
+            {\r
+            var row = resultRows.item(i);\r
+\r
+            if (row.className == "SRResult")\r
+                {\r
+                var rowMatchName = row.id.toLowerCase();\r
+                rowMatchName = rowMatchName.replace(/^sr\d*_/, '');\r
+\r
+                if (search.length <= rowMatchName.length && rowMatchName.substr(0, search.length) == search)\r
+                    {\r
+                    row.style.display = "block";\r
+                    matches++;\r
+                    }\r
+                else\r
+                    {  row.style.display = "none";  };\r
+                };\r
+\r
+            i++;\r
+            };\r
+\r
+        document.getElementById("Searching").style.display="none";\r
+\r
+        if (matches == 0)\r
+            {  document.getElementById("NoMatches").style.display="block";  }\r
+        else\r
+            {  document.getElementById("NoMatches").style.display="none";  }\r
+\r
+        this.lastMatchCount = matches;\r
+\r
+        return true;\r
+        };\r
+    };\r
+\r
diff --git a/docs/html/javascript/searchdata.js b/docs/html/javascript/searchdata.js
new file mode 100644 (file)
index 0000000..9dcca5a
--- /dev/null
@@ -0,0 +1,62 @@
+var indexSectionsWithContent = {
+   "General": {
+      "Symbols": false,
+      "Numbers": false,
+      "A": true,
+      "B": false,
+      "C": false,
+      "D": false,
+      "E": false,
+      "F": true,
+      "G": false,
+      "H": false,
+      "I": false,
+      "J": false,
+      "K": false,
+      "L": false,
+      "M": true,
+      "N": false,
+      "O": false,
+      "P": false,
+      "Q": false,
+      "R": false,
+      "S": true,
+      "T": false,
+      "U": false,
+      "V": false,
+      "W": false,
+      "X": false,
+      "Y": false,
+      "Z": false
+      },
+   "Functions": {
+      "Symbols": false,
+      "Numbers": false,
+      "A": true,
+      "B": false,
+      "C": false,
+      "D": false,
+      "E": false,
+      "F": false,
+      "G": false,
+      "H": false,
+      "I": false,
+      "J": false,
+      "K": false,
+      "L": false,
+      "M": false,
+      "N": false,
+      "O": false,
+      "P": false,
+      "Q": false,
+      "R": false,
+      "S": false,
+      "T": false,
+      "U": false,
+      "V": false,
+      "W": false,
+      "X": false,
+      "Y": false,
+      "Z": false
+      }
+   }
\ No newline at end of file
diff --git a/docs/html/search/FunctionsA.html b/docs/html/search/FunctionsA.html
new file mode 100644 (file)
index 0000000..d6f66d4
--- /dev/null
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+
+<html><head><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
+if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
+
+<!--  Generated by Natural Docs, version 1.4 -->
+<!--  http://www.naturaldocs.org  -->
+
+<!-- saved from url=(0026)http://www.naturaldocs.org -->
+
+
+
+
+<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_alureBufferDataFromFile><div class=IEntry><a href="../files/buffer-cpp.html#alureBufferDataFromFile" target=_parent class=ISymbol>alureBufferDataFromFile</a></div></div><div class=SRResult id=SR_alureBufferDataFromMemory><div class=IEntry><a href="../files/buffer-cpp.html#alureBufferDataFromMemory" target=_parent class=ISymbol>alureBufferDataFromMemory</a></div></div><div class=SRResult id=SR_alureBufferDataFromStream><div class=IEntry><a href="../files/stream-cpp.html#alureBufferDataFromStream" target=_parent class=ISymbol>alureBufferDataFromStream</a></div></div><div class=SRResult id=SR_alureCreateBufferFromFile><div class=IEntry><a href="../files/buffer-cpp.html#alureCreateBufferFromFile" target=_parent class=ISymbol>alureCreateBufferFromFile</a></div></div><div class=SRResult id=SR_alureCreateBufferFromMemory><div class=IEntry><a href="../files/buffer-cpp.html#alureCreateBufferFromMemory" target=_parent class=ISymbol>alureCreateBufferFromMemory</a></div></div><div class=SRResult id=SR_alureCreateStreamFromCallback><div class=IEntry><a href="../files/stream-cpp.html#alureCreateStreamFromCallback" target=_parent class=ISymbol>alureCreateStreamFromCallback</a></div></div><div class=SRResult id=SR_alureCreateStreamFromFile><div class=IEntry><a href="../files/stream-cpp.html#alureCreateStreamFromFile" target=_parent class=ISymbol>alureCreateStreamFromFile</a></div></div><div class=SRResult id=SR_alureCreateStreamFromMemory><div class=IEntry><a href="../files/stream-cpp.html#alureCreateStreamFromMemory" target=_parent class=ISymbol>alureCreateStreamFromMemory</a></div></div><div class=SRResult id=SR_alureCreateStreamFromStaticMemory><div class=IEntry><a href="../files/stream-cpp.html#alureCreateStreamFromStaticMemory" target=_parent class=ISymbol>alureCreateStreamFromStaticMemory</a></div></div><div class=SRResult id=SR_alureDestroyStream><div class=IEntry><a href="../files/stream-cpp.html#alureDestroyStream" target=_parent class=ISymbol>alureDestroyStream</a></div></div><div class=SRResult id=SR_alureFreeDeviceNames><div class=IEntry><a href="../files/alure-cpp.html#alureFreeDeviceNames" target=_parent class=ISymbol>alureFreeDeviceNames</a></div></div><div class=SRResult id=SR_alureGetDeviceNames><div class=IEntry><a href="../files/alure-cpp.html#alureGetDeviceNames" target=_parent class=ISymbol>alureGetDeviceNames</a></div></div><div class=SRResult id=SR_alureGetErrorString><div class=IEntry><a href="../files/alure-cpp.html#alureGetErrorString" target=_parent class=ISymbol>alureGetErrorString</a></div></div><div class=SRResult id=SR_alureGetProcAddress><div class=IEntry><a href="../files/alure-cpp.html#alureGetProcAddress" target=_parent class=ISymbol>alureGetProcAddress</a></div></div><div class=SRResult id=SR_alureGetSampleFormat><div class=IEntry><a href="../files/alure-cpp.html#alureGetSampleFormat" target=_parent class=ISymbol>alureGetSampleFormat</a></div></div><div class=SRResult id=SR_alureGetStreamFrequency><div class=IEntry><a href="../files/stream-cpp.html#alureGetStreamFrequency" target=_parent class=ISymbol>alureGetStreamFrequency</a></div></div><div class=SRResult id=SR_alureGetStreamLength><div class=IEntry><a href="../files/stream-cpp.html#alureGetStreamLength" target=_parent class=ISymbol>alureGetStreamLength</a></div></div><div class=SRResult id=SR_alureGetVersion><div class=IEntry><a href="../files/alure-cpp.html#alureGetVersion" target=_parent class=ISymbol>alureGetVersion</a></div></div><div class=SRResult id=SR_alureInitDevice><div class=IEntry><a href="../files/alure-cpp.html#alureInitDevice" target=_parent class=ISymbol>alureInitDevice</a></div></div><div class=SRResult id=SR_alureInstallDecodeCallbacks><div class=IEntry><a href="../files/alure-cpp.html#alureInstallDecodeCallbacks" target=_parent class=ISymbol>alureInstallDecodeCallbacks</a></div></div><div class=SRResult id=SR_alurePauseSource><div class=IEntry><a href="../files/streamplay-cpp.html#alurePauseSource" target=_parent class=ISymbol>alurePauseSource</a></div></div><div class=SRResult id=SR_alurePlaySource><div class=IEntry><a href="../files/streamplay-cpp.html#alurePlaySource" target=_parent class=ISymbol>alurePlaySource</a></div></div><div class=SRResult id=SR_alurePlaySourceStream><div class=IEntry><a href="../files/streamplay-cpp.html#alurePlaySourceStream" target=_parent class=ISymbol>alurePlaySourceStream</a></div></div><div class=SRResult id=SR_alureResumeSource><div class=IEntry><a href="../files/streamplay-cpp.html#alureResumeSource" target=_parent class=ISymbol>alureResumeSource</a></div></div><div class=SRResult id=SR_alureRewindStream><div class=IEntry><a href="../files/stream-cpp.html#alureRewindStream" target=_parent class=ISymbol>alureRewindStream</a></div></div><div class=SRResult id=SR_alureSetIOCallbacks><div class=IEntry><a href="../files/istream-cpp.html#alureSetIOCallbacks" target=_parent class=ISymbol>alureSetIOCallbacks</a></div></div><div class=SRResult id=SR_alureSetStreamOrder><div class=IEntry><a href="../files/stream-cpp.html#alureSetStreamOrder" target=_parent class=ISymbol>alureSetStreamOrder</a></div></div><div class=SRResult id=SR_alureSetStreamPatchset><div class=IEntry><a href="../files/stream-cpp.html#alureSetStreamPatchset" target=_parent class=ISymbol>alureSetStreamPatchset</a></div></div><div class=SRResult id=SR_alureShutdownDevice><div class=IEntry><a href="../files/alure-cpp.html#alureShutdownDevice" target=_parent class=ISymbol>alureShutdownDevice</a></div></div><div class=SRResult id=SR_alureSleep><div class=IEntry><a href="../files/alure-cpp.html#alureSleep" target=_parent class=ISymbol>alureSleep</a></div></div><div class=SRResult id=SR_alureStopSource><div class=IEntry><a href="../files/streamplay-cpp.html#alureStopSource" target=_parent class=ISymbol>alureStopSource</a></div></div><div class=SRResult id=SR_alureStreamSizeIsMicroSec><div class=IEntry><a href="../files/stream-cpp.html#alureStreamSizeIsMicroSec" target=_parent class=ISymbol>alureStreamSizeIsMicroSec</a></div></div><div class=SRResult id=SR_alureUpdate><div class=IEntry><a href="../files/streamplay-cpp.html#alureUpdate" target=_parent class=ISymbol>alureUpdate</a></div></div><div class=SRResult id=SR_alureUpdateInterval><div class=IEntry><a href="../files/streamplay-cpp.html#alureUpdateInterval" target=_parent class=ISymbol>alureUpdateInterval</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults", "HTML");
+searchResults.Search();
+--></script></div><script language=JavaScript><!--
+if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
\ No newline at end of file
diff --git a/docs/html/search/GeneralA.html b/docs/html/search/GeneralA.html
new file mode 100644 (file)
index 0000000..77af41b
--- /dev/null
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+
+<html><head><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
+if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
+
+<!--  Generated by Natural Docs, version 1.4 -->
+<!--  http://www.naturaldocs.org  -->
+
+<!-- saved from url=(0026)http://www.naturaldocs.org -->
+
+
+
+
+<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_alureBufferDataFromFile><div class=IEntry><a href="../files/buffer-cpp.html#alureBufferDataFromFile" target=_parent class=ISymbol>alureBufferDataFromFile</a></div></div><div class=SRResult id=SR_alureBufferDataFromMemory><div class=IEntry><a href="../files/buffer-cpp.html#alureBufferDataFromMemory" target=_parent class=ISymbol>alureBufferDataFromMemory</a></div></div><div class=SRResult id=SR_alureBufferDataFromStream><div class=IEntry><a href="../files/stream-cpp.html#alureBufferDataFromStream" target=_parent class=ISymbol>alureBufferDataFromStream</a></div></div><div class=SRResult id=SR_alureCreateBufferFromFile><div class=IEntry><a href="../files/buffer-cpp.html#alureCreateBufferFromFile" target=_parent class=ISymbol>alureCreateBufferFromFile</a></div></div><div class=SRResult id=SR_alureCreateBufferFromMemory><div class=IEntry><a href="../files/buffer-cpp.html#alureCreateBufferFromMemory" target=_parent class=ISymbol>alureCreateBufferFromMemory</a></div></div><div class=SRResult id=SR_alureCreateStreamFromCallback><div class=IEntry><a href="../files/stream-cpp.html#alureCreateStreamFromCallback" target=_parent class=ISymbol>alureCreateStreamFromCallback</a></div></div><div class=SRResult id=SR_alureCreateStreamFromFile><div class=IEntry><a href="../files/stream-cpp.html#alureCreateStreamFromFile" target=_parent class=ISymbol>alureCreateStreamFromFile</a></div></div><div class=SRResult id=SR_alureCreateStreamFromMemory><div class=IEntry><a href="../files/stream-cpp.html#alureCreateStreamFromMemory" target=_parent class=ISymbol>alureCreateStreamFromMemory</a></div></div><div class=SRResult id=SR_alureCreateStreamFromStaticMemory><div class=IEntry><a href="../files/stream-cpp.html#alureCreateStreamFromStaticMemory" target=_parent class=ISymbol>alureCreateStreamFromStaticMemory</a></div></div><div class=SRResult id=SR_alureDestroyStream><div class=IEntry><a href="../files/stream-cpp.html#alureDestroyStream" target=_parent class=ISymbol>alureDestroyStream</a></div></div><div class=SRResult id=SR_alureFreeDeviceNames><div class=IEntry><a href="../files/alure-cpp.html#alureFreeDeviceNames" target=_parent class=ISymbol>alureFreeDeviceNames</a></div></div><div class=SRResult id=SR_alureGetDeviceNames><div class=IEntry><a href="../files/alure-cpp.html#alureGetDeviceNames" target=_parent class=ISymbol>alureGetDeviceNames</a></div></div><div class=SRResult id=SR_alureGetErrorString><div class=IEntry><a href="../files/alure-cpp.html#alureGetErrorString" target=_parent class=ISymbol>alureGetErrorString</a></div></div><div class=SRResult id=SR_alureGetProcAddress><div class=IEntry><a href="../files/alure-cpp.html#alureGetProcAddress" target=_parent class=ISymbol>alureGetProcAddress</a></div></div><div class=SRResult id=SR_alureGetSampleFormat><div class=IEntry><a href="../files/alure-cpp.html#alureGetSampleFormat" target=_parent class=ISymbol>alureGetSampleFormat</a></div></div><div class=SRResult id=SR_alureGetStreamFrequency><div class=IEntry><a href="../files/stream-cpp.html#alureGetStreamFrequency" target=_parent class=ISymbol>alureGetStreamFrequency</a></div></div><div class=SRResult id=SR_alureGetStreamLength><div class=IEntry><a href="../files/stream-cpp.html#alureGetStreamLength" target=_parent class=ISymbol>alureGetStreamLength</a></div></div><div class=SRResult id=SR_alureGetVersion><div class=IEntry><a href="../files/alure-cpp.html#alureGetVersion" target=_parent class=ISymbol>alureGetVersion</a></div></div><div class=SRResult id=SR_alureInitDevice><div class=IEntry><a href="../files/alure-cpp.html#alureInitDevice" target=_parent class=ISymbol>alureInitDevice</a></div></div><div class=SRResult id=SR_alureInstallDecodeCallbacks><div class=IEntry><a href="../files/alure-cpp.html#alureInstallDecodeCallbacks" target=_parent class=ISymbol>alureInstallDecodeCallbacks</a></div></div><div class=SRResult id=SR_alurePauseSource><div class=IEntry><a href="../files/streamplay-cpp.html#alurePauseSource" target=_parent class=ISymbol>alurePauseSource</a></div></div><div class=SRResult id=SR_alurePlaySource><div class=IEntry><a href="../files/streamplay-cpp.html#alurePlaySource" target=_parent class=ISymbol>alurePlaySource</a></div></div><div class=SRResult id=SR_alurePlaySourceStream><div class=IEntry><a href="../files/streamplay-cpp.html#alurePlaySourceStream" target=_parent class=ISymbol>alurePlaySourceStream</a></div></div><div class=SRResult id=SR_alureResumeSource><div class=IEntry><a href="../files/streamplay-cpp.html#alureResumeSource" target=_parent class=ISymbol>alureResumeSource</a></div></div><div class=SRResult id=SR_alureRewindStream><div class=IEntry><a href="../files/stream-cpp.html#alureRewindStream" target=_parent class=ISymbol>alureRewindStream</a></div></div><div class=SRResult id=SR_alureSetIOCallbacks><div class=IEntry><a href="../files/istream-cpp.html#alureSetIOCallbacks" target=_parent class=ISymbol>alureSetIOCallbacks</a></div></div><div class=SRResult id=SR_alureSetStreamOrder><div class=IEntry><a href="../files/stream-cpp.html#alureSetStreamOrder" target=_parent class=ISymbol>alureSetStreamOrder</a></div></div><div class=SRResult id=SR_alureSetStreamPatchset><div class=IEntry><a href="../files/stream-cpp.html#alureSetStreamPatchset" target=_parent class=ISymbol>alureSetStreamPatchset</a></div></div><div class=SRResult id=SR_alureShutdownDevice><div class=IEntry><a href="../files/alure-cpp.html#alureShutdownDevice" target=_parent class=ISymbol>alureShutdownDevice</a></div></div><div class=SRResult id=SR_alureSleep><div class=IEntry><a href="../files/alure-cpp.html#alureSleep" target=_parent class=ISymbol>alureSleep</a></div></div><div class=SRResult id=SR_alureStopSource><div class=IEntry><a href="../files/streamplay-cpp.html#alureStopSource" target=_parent class=ISymbol>alureStopSource</a></div></div><div class=SRResult id=SR_alureStreamSizeIsMicroSec><div class=IEntry><a href="../files/stream-cpp.html#alureStreamSizeIsMicroSec" target=_parent class=ISymbol>alureStreamSizeIsMicroSec</a></div></div><div class=SRResult id=SR_alureUpdate><div class=IEntry><a href="../files/streamplay-cpp.html#alureUpdate" target=_parent class=ISymbol>alureUpdate</a></div></div><div class=SRResult id=SR_alureUpdateInterval><div class=IEntry><a href="../files/streamplay-cpp.html#alureUpdateInterval" target=_parent class=ISymbol>alureUpdateInterval</a></div></div><div class=SRResult id=SR_Automatic_spcPlayback><div class=IEntry><a href="../files/streamplay-cpp.html#Automatic_Playback" target=_parent class=ISymbol>Automatic Playback</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults", "HTML");
+searchResults.Search();
+--></script></div><script language=JavaScript><!--
+if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
\ No newline at end of file
diff --git a/docs/html/search/GeneralF.html b/docs/html/search/GeneralF.html
new file mode 100644 (file)
index 0000000..89aa88b
--- /dev/null
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+
+<html><head><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
+if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
+
+<!--  Generated by Natural Docs, version 1.4 -->
+<!--  http://www.naturaldocs.org  -->
+
+<!-- saved from url=(0026)http://www.naturaldocs.org -->
+
+
+
+
+<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_File_spcI_slaO><div class=IEntry><a href="../files/istream-cpp.html#File_I/O" target=_parent class=ISymbol>File I/<wbr>O</a></div></div><div class=SRResult id=SR_File_spcLoading><div class=IEntry><a href="../files/buffer-cpp.html#File_Loading" target=_parent class=ISymbol>File Loading</a></div></div><div class=SRResult id=SR_Functions><div class=IEntry><a href="javascript:searchResults.Toggle('SR_Functions')" class=ISymbol>Functions</a><div class=ISubIndex><a href="../files/alure-cpp.html#Functions" target=_parent class=IFile>alure.cpp</a><a href="../files/buffer-cpp.html#Functions" target=_parent class=IFile>buffer.cpp</a><a href="../files/istream-cpp.html#Functions" target=_parent class=IFile>istream.cpp</a><a href="../files/stream-cpp.html#Functions" target=_parent class=IFile>stream.cpp</a><a href="../files/streamplay-cpp.html#Functions" target=_parent class=IFile>streamplay.cpp</a></div></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults", "HTML");
+searchResults.Search();
+--></script></div><script language=JavaScript><!--
+if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
\ No newline at end of file
diff --git a/docs/html/search/GeneralM.html b/docs/html/search/GeneralM.html
new file mode 100644 (file)
index 0000000..c3e97d8
--- /dev/null
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+
+<html><head><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
+if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
+
+<!--  Generated by Natural Docs, version 1.4 -->
+<!--  http://www.naturaldocs.org  -->
+
+<!-- saved from url=(0026)http://www.naturaldocs.org -->
+
+
+
+
+<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_Main_spcand_spcMiscellanious><div class=IEntry><a href="../files/alure-cpp.html#Main_and_Miscellanious" target=_parent class=ISymbol>Main and Miscellanious</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults", "HTML");
+searchResults.Search();
+--></script></div><script language=JavaScript><!--
+if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
\ No newline at end of file
diff --git a/docs/html/search/GeneralS.html b/docs/html/search/GeneralS.html
new file mode 100644 (file)
index 0000000..6d18abb
--- /dev/null
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+
+<html><head><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
+if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
+
+<!--  Generated by Natural Docs, version 1.4 -->
+<!--  http://www.naturaldocs.org  -->
+
+<!-- saved from url=(0026)http://www.naturaldocs.org -->
+
+
+
+
+<div id=Index><div class=SRStatus id=Loading>Loading...</div><table border=0 cellspacing=0 cellpadding=0><div class=SRResult id=SR_Streaming><div class=IEntry><a href="../files/stream-cpp.html#Streaming" target=_parent class=ISymbol>Streaming</a></div></div></table><div class=SRStatus id=Searching>Searching...</div><div class=SRStatus id=NoMatches>No Matches</div><script type="text/javascript"><!--
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults", "HTML");
+searchResults.Search();
+--></script></div><script language=JavaScript><!--
+if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
\ No newline at end of file
diff --git a/docs/html/search/NoResults.html b/docs/html/search/NoResults.html
new file mode 100644 (file)
index 0000000..02ce888
--- /dev/null
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+
+<html><head><link rel="stylesheet" type="text/css" href="../styles/main.css"><script language=JavaScript src="../javascript/main.js"></script></head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()"><script language=JavaScript><!--
+if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script>
+
+<!--  Generated by Natural Docs, version 1.4 -->
+<!--  http://www.naturaldocs.org  -->
+
+<!-- saved from url=(0026)http://www.naturaldocs.org -->
+
+
+
+
+<div id=Index><div class=SRStatus id=NoMatches>No Matches</div></div><script language=JavaScript><!--
+if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html>
\ No newline at end of file
diff --git a/docs/html/styles/1.css b/docs/html/styles/1.css
new file mode 100644 (file)
index 0000000..17e9cbc
--- /dev/null
@@ -0,0 +1,767 @@
+/*\r
+   IMPORTANT: If you're editing this file in the output directory of one of\r
+   your projects, your changes will be overwritten the next time you run\r
+   Natural Docs.  Instead, copy this file to your project directory, make your\r
+   changes, and you can use it with -s.  Even better would be to make a CSS\r
+   file in your project directory with only your changes, which you can then\r
+   use with -s [original style] [your changes].\r
+\r
+   On the other hand, if you're editing this file in the Natural Docs styles\r
+   directory, the changes will automatically be applied to all your projects\r
+   that use this style the next time Natural Docs is run on them.\r
+\r
+   This file is part of Natural Docs, which is Copyright (C) 2003-2008 Greg Valure\r
+   Natural Docs is licensed under the GPL\r
+*/\r
+\r
+body {\r
+    font: 10pt Verdana, Arial, sans-serif;\r
+    color: #000000;\r
+    margin: 0; padding: 0;\r
+    }\r
+\r
+.ContentPage,\r
+.IndexPage,\r
+.FramedMenuPage {\r
+    background-color: #E8E8E8;\r
+    }\r
+.FramedContentPage,\r
+.FramedIndexPage,\r
+.FramedSearchResultsPage,\r
+.PopupSearchResultsPage {\r
+    background-color: #FFFFFF;\r
+    }\r
+\r
+\r
+a:link,\r
+a:visited { color: #900000; text-decoration: none }\r
+a:hover { color: #900000; text-decoration: underline }\r
+a:active { color: #FF0000; text-decoration: underline }\r
+\r
+td {\r
+    vertical-align: top }\r
+\r
+img { border: 0;  }\r
+\r
+\r
+/*\r
+    Comment out this line to use web-style paragraphs (blank line between\r
+    paragraphs, no indent) instead of print-style paragraphs (no blank line,\r
+    indented.)\r
+*/\r
+p {\r
+    text-indent: 5ex; margin: 0 }\r
+\r
+\r
+/*  Opera doesn't break with just wbr, but will if you add this.  */\r
+.Opera wbr:after {\r
+       content: "\00200B";\r
+       }\r
+\r
+\r
+/*  Blockquotes are used as containers for things that may need to scroll.  */\r
+blockquote {\r
+    padding: 0;\r
+    margin: 0;\r
+    overflow: auto;\r
+    }\r
+\r
+\r
+.Firefox1 blockquote {\r
+    padding-bottom: .5em;\r
+    }\r
+\r
+/*  Turn off scrolling when printing.  */\r
+@media print {\r
+    blockquote {\r
+        overflow: visible;\r
+        }\r
+    .IE blockquote {\r
+        width: auto;\r
+        }\r
+    }\r
+\r
+\r
+\r
+#Menu {\r
+    font-size: 9pt;\r
+    padding: 10px 0 0 0;\r
+    }\r
+.ContentPage #Menu,\r
+.IndexPage #Menu {\r
+    position: absolute;\r
+    top: 0;\r
+    left: 0;\r
+    width: 31ex;\r
+    overflow: hidden;\r
+    }\r
+.ContentPage .Firefox #Menu,\r
+.IndexPage .Firefox #Menu {\r
+    width: 27ex;\r
+    }\r
+\r
+\r
+    .MTitle {\r
+        font-size: 16pt; font-weight: bold; font-variant: small-caps;\r
+        text-align: center;\r
+        padding: 5px 10px 15px 10px;\r
+        border-bottom: 1px dotted #000000;\r
+        margin-bottom: 15px }\r
+\r
+    .MSubTitle {\r
+        font-size: 9pt; font-weight: normal; font-variant: normal;\r
+        margin-top: 1ex; margin-bottom: 5px }\r
+\r
+\r
+    .MEntry a:link,\r
+    .MEntry a:hover,\r
+    .MEntry a:visited { color: #606060; margin-right: 0 }\r
+    .MEntry a:active { color: #A00000; margin-right: 0 }\r
+\r
+\r
+    .MGroup {\r
+        font-variant: small-caps; font-weight: bold;\r
+        margin: 1em 0 1em 10px;\r
+        }\r
+\r
+    .MGroupContent {\r
+        font-variant: normal; font-weight: normal }\r
+\r
+    .MGroup a:link,\r
+    .MGroup a:hover,\r
+    .MGroup a:visited { color: #545454; margin-right: 10px }\r
+    .MGroup a:active { color: #A00000; margin-right: 10px }\r
+\r
+\r
+    .MFile,\r
+    .MText,\r
+    .MLink,\r
+    .MIndex {\r
+        padding: 1px 17px 2px 10px;\r
+        margin: .25em 0 .25em 0;\r
+        }\r
+\r
+    .MText {\r
+        font-size: 8pt; font-style: italic }\r
+\r
+    .MLink {\r
+        font-style: italic }\r
+\r
+    #MSelected {\r
+        color: #000000; background-color: #FFFFFF;\r
+        /*  Replace padding with border.  */\r
+        padding: 0 10px 0 10px;\r
+        border-width: 1px 2px 2px 0; border-style: solid; border-color: #000000;\r
+        margin-right: 5px;\r
+        }\r
+\r
+    /*  Close off the left side when its in a group.  */\r
+    .MGroup #MSelected {\r
+        padding-left: 9px; border-left-width: 1px }\r
+\r
+    /*  A treat for Mozilla users.  Blatantly non-standard.  Will be replaced with CSS 3 attributes when finalized/supported.  */\r
+    .Firefox #MSelected {\r
+        -moz-border-radius-topright: 10px;\r
+        -moz-border-radius-bottomright: 10px }\r
+    .Firefox .MGroup #MSelected {\r
+        -moz-border-radius-topleft: 10px;\r
+        -moz-border-radius-bottomleft: 10px }\r
+\r
+\r
+    #MSearchPanel {\r
+        padding: 0px 6px;\r
+        margin: .25em 0;\r
+        }\r
+\r
+\r
+    #MSearchField {\r
+        font: italic 9pt Verdana, sans-serif;\r
+        color: #606060;\r
+        background-color: #E8E8E8;\r
+        border: none;\r
+        padding: 2px 4px;\r
+        width: 100%;\r
+        }\r
+    /* Only Opera gets it right. */\r
+    .Firefox #MSearchField,\r
+    .IE #MSearchField,\r
+    .Safari #MSearchField {\r
+        width: 94%;\r
+        }\r
+    .Opera9 #MSearchField,\r
+    .Konqueror #MSearchField {\r
+        width: 97%;\r
+        }\r
+    .FramedMenuPage .Firefox #MSearchField,\r
+    .FramedMenuPage .Safari #MSearchField,\r
+    .FramedMenuPage .Konqueror #MSearchField {\r
+        width: 98%;\r
+        }\r
+\r
+    /* Firefox doesn't do this right in frames without #MSearchPanel added on.\r
+        It's presence doesn't hurt anything other browsers. */\r
+    #MSearchPanel.MSearchPanelInactive:hover #MSearchField {\r
+        background-color: #FFFFFF;\r
+        border: 1px solid #C0C0C0;\r
+        padding: 1px 3px;\r
+        }\r
+    .MSearchPanelActive #MSearchField {\r
+        background-color: #FFFFFF;\r
+        border: 1px solid #C0C0C0;\r
+        font-style: normal;\r
+        padding: 1px 3px;\r
+        }\r
+\r
+    #MSearchType {\r
+        visibility: hidden;\r
+        font: 8pt Verdana, sans-serif;\r
+        width: 98%;\r
+        padding: 0;\r
+        border: 1px solid #C0C0C0;\r
+        }\r
+    .MSearchPanelActive #MSearchType,\r
+    /*  As mentioned above, Firefox doesn't do this right in frames without #MSearchPanel added on. */\r
+    #MSearchPanel.MSearchPanelInactive:hover #MSearchType,\r
+    #MSearchType:focus {\r
+        visibility: visible;\r
+        color: #606060;\r
+        }\r
+    #MSearchType option#MSearchEverything {\r
+        font-weight: bold;\r
+        }\r
+\r
+    .Opera8 .MSearchPanelInactive:hover,\r
+    .Opera8 .MSearchPanelActive {\r
+        margin-left: -1px;\r
+        }\r
+\r
+\r
+    iframe#MSearchResults {\r
+        width: 60ex;\r
+        height: 15em;\r
+        }\r
+    #MSearchResultsWindow {\r
+        display: none;\r
+        position: absolute;\r
+        left: 0; top: 0;\r
+        border: 1px solid #000000;\r
+        background-color: #E8E8E8;\r
+        }\r
+    #MSearchResultsWindowClose {\r
+        font-weight: bold;\r
+        font-size: 8pt;\r
+        display: block;\r
+        padding: 2px 5px;\r
+        }\r
+    #MSearchResultsWindowClose:link,\r
+    #MSearchResultsWindowClose:visited {\r
+        color: #000000;\r
+        text-decoration: none;\r
+        }\r
+    #MSearchResultsWindowClose:active,\r
+    #MSearchResultsWindowClose:hover {\r
+        color: #800000;\r
+        text-decoration: none;\r
+        background-color: #F4F4F4;\r
+        }\r
+\r
+\r
+\r
+\r
+#Content {\r
+    padding-bottom: 15px;\r
+    }\r
+\r
+.ContentPage #Content {\r
+    border-width: 0 0 1px 1px;\r
+    border-style: solid;\r
+    border-color: #000000;\r
+    background-color: #FFFFFF;\r
+    font-size: 9pt;  /* To make 31ex match the menu's 31ex. */\r
+    margin-left: 31ex;\r
+    }\r
+.ContentPage .Firefox #Content {\r
+    margin-left: 27ex;\r
+    }\r
+\r
+\r
+\r
+    .CTopic {\r
+        font-size: 10pt;\r
+        margin-bottom: 3em;\r
+        }\r
+\r
+\r
+    .CTitle {\r
+        font-size: 12pt; font-weight: bold;\r
+        border-width: 0 0 1px 0; border-style: solid; border-color: #A0A0A0;\r
+        margin: 0 15px .5em 15px }\r
+\r
+    .CGroup .CTitle {\r
+        font-size: 16pt; font-variant: small-caps;\r
+        padding-left: 15px; padding-right: 15px;\r
+        border-width: 0 0 2px 0; border-color: #000000;\r
+        margin-left: 0; margin-right: 0 }\r
+\r
+    .CClass .CTitle,\r
+    .CInterface .CTitle,\r
+    .CDatabase .CTitle,\r
+    .CDatabaseTable .CTitle,\r
+    .CSection .CTitle {\r
+        font-size: 18pt;\r
+        color: #FFFFFF; background-color: #A0A0A0;\r
+        padding: 10px 15px 10px 15px;\r
+        border-width: 2px 0; border-color: #000000;\r
+        margin-left: 0; margin-right: 0 }\r
+\r
+    #MainTopic .CTitle {\r
+        font-size: 20pt;\r
+        color: #FFFFFF; background-color: #7070C0;\r
+        padding: 10px 15px 10px 15px;\r
+        border-width: 0 0 3px 0; border-color: #000000;\r
+        margin-left: 0; margin-right: 0 }\r
+\r
+    .CBody {\r
+        margin-left: 15px; margin-right: 15px }\r
+\r
+\r
+    .CToolTip {\r
+        position: absolute; visibility: hidden;\r
+        left: 0; top: 0;\r
+        background-color: #FFFFE0;\r
+        padding: 5px;\r
+        border-width: 1px 2px 2px 1px; border-style: solid; border-color: #000000;\r
+        font-size: 8pt;\r
+        }\r
+\r
+    .Opera .CToolTip {\r
+        max-width: 98%;\r
+        }\r
+\r
+    /*  Scrollbars would be useless.  */\r
+    .CToolTip blockquote {\r
+        overflow: hidden;\r
+        }\r
+    .IE6 .CToolTip blockquote {\r
+        overflow: visible;\r
+        }\r
+\r
+    .CHeading {\r
+        font-weight: bold; font-size: 10pt;\r
+        margin: 1.5em 0 .5em 0;\r
+        }\r
+\r
+    .CBody pre {\r
+        font: 10pt "Courier New", Courier, monospace;\r
+        margin: 1em 0;\r
+        }\r
+\r
+    .CBody ul {\r
+        /*  I don't know why CBody's margin doesn't apply, but it's consistent across browsers so whatever.\r
+             Reapply it here as padding.  */\r
+        padding-left: 15px; padding-right: 15px;\r
+        margin: .5em 5ex .5em 5ex;\r
+        }\r
+\r
+    .CDescriptionList {\r
+        margin: .5em 5ex 0 5ex }\r
+\r
+        .CDLEntry {\r
+            font: 10pt "Courier New", Courier, monospace; color: #808080;\r
+            padding-bottom: .25em;\r
+            white-space: nowrap }\r
+\r
+        .CDLDescription {\r
+            font-size: 10pt;  /*  For browsers that don't inherit correctly, like Opera 5.  */\r
+            padding-bottom: .5em; padding-left: 5ex }\r
+\r
+\r
+    .CTopic img {\r
+        text-align: center;\r
+        display: block;\r
+        margin: 1em auto;\r
+        }\r
+    .CImageCaption {\r
+        font-variant: small-caps;\r
+        font-size: 8pt;\r
+        color: #808080;\r
+        text-align: center;\r
+        position: relative;\r
+        top: 1em;\r
+        }\r
+\r
+    .CImageLink {\r
+        color: #808080;\r
+        font-style: italic;\r
+        }\r
+    a.CImageLink:link,\r
+    a.CImageLink:visited,\r
+    a.CImageLink:hover { color: #808080 }\r
+\r
+\r
+\r
+\r
+\r
+.Prototype {\r
+    font: 10pt "Courier New", Courier, monospace;\r
+    padding: 5px 3ex;\r
+    border-width: 1px; border-style: solid;\r
+    margin: 0 5ex 1.5em 5ex;\r
+    }\r
+\r
+    .Prototype td {\r
+        font-size: 10pt;\r
+        }\r
+\r
+    .PDefaultValue,\r
+    .PDefaultValuePrefix,\r
+    .PTypePrefix {\r
+        color: #8F8F8F;\r
+        }\r
+    .PTypePrefix {\r
+        text-align: right;\r
+        }\r
+    .PAfterParameters {\r
+        vertical-align: bottom;\r
+        }\r
+\r
+    .IE .Prototype table {\r
+        padding: 0;\r
+        }\r
+\r
+    .CFunction .Prototype {\r
+        background-color: #F4F4F4; border-color: #D0D0D0 }\r
+    .CProperty .Prototype {\r
+        background-color: #F4F4FF; border-color: #C0C0E8 }\r
+    .CVariable .Prototype {\r
+        background-color: #FFFFF0; border-color: #E0E0A0 }\r
+\r
+    .CClass .Prototype {\r
+        border-width: 1px 2px 2px 1px; border-style: solid; border-color: #A0A0A0;\r
+        background-color: #F4F4F4;\r
+        }\r
+    .CInterface .Prototype {\r
+        border-width: 1px 2px 2px 1px; border-style: solid; border-color: #A0A0D0;\r
+        background-color: #F4F4FF;\r
+        }\r
+\r
+    .CDatabaseIndex .Prototype,\r
+    .CConstant .Prototype {\r
+        background-color: #D0D0D0; border-color: #000000 }\r
+    .CType .Prototype,\r
+    .CEnumeration .Prototype {\r
+        background-color: #FAF0F0; border-color: #E0B0B0;\r
+        }\r
+    .CDatabaseTrigger .Prototype,\r
+    .CEvent .Prototype,\r
+    .CDelegate .Prototype {\r
+        background-color: #F0FCF0; border-color: #B8E4B8 }\r
+\r
+    .CToolTip .Prototype {\r
+        margin: 0 0 .5em 0;\r
+        white-space: nowrap;\r
+        }\r
+\r
+\r
+\r
+\r
+\r
+.Summary {\r
+    margin: 1.5em 5ex 0 5ex }\r
+\r
+    .STitle {\r
+        font-size: 12pt; font-weight: bold;\r
+        margin-bottom: .5em }\r
+\r
+\r
+    .SBorder {\r
+        background-color: #FFFFF0;\r
+        padding: 15px;\r
+        border: 1px solid #C0C060 }\r
+\r
+    /* In a frame IE 6 will make them too long unless you set the width to 100%.  Without frames it will be correct without a width\r
+        or slightly too long (but not enough to scroll) with a width.  This arbitrary weirdness simply astounds me.  IE 7 has the same\r
+        problem with frames, haven't tested it without.  */\r
+    .FramedContentPage .IE .SBorder {\r
+        width: 100% }\r
+\r
+    /*  A treat for Mozilla users.  Blatantly non-standard.  Will be replaced with CSS 3 attributes when finalized/supported.  */\r
+    .Firefox .SBorder {\r
+        -moz-border-radius: 20px }\r
+\r
+\r
+    .STable {\r
+        font-size: 9pt; width: 100% }\r
+\r
+    .SEntry {\r
+        width: 30% }\r
+    .SDescription {\r
+        width: 70% }\r
+\r
+\r
+    .SMarked {\r
+        background-color: #F8F8D8 }\r
+\r
+    .SDescription { padding-left: 2ex }\r
+    .SIndent1 .SEntry { padding-left: 1.5ex }   .SIndent1 .SDescription { padding-left: 3.5ex }\r
+    .SIndent2 .SEntry { padding-left: 3.0ex }   .SIndent2 .SDescription { padding-left: 5.0ex }\r
+    .SIndent3 .SEntry { padding-left: 4.5ex }   .SIndent3 .SDescription { padding-left: 6.5ex }\r
+    .SIndent4 .SEntry { padding-left: 6.0ex }   .SIndent4 .SDescription { padding-left: 8.0ex }\r
+    .SIndent5 .SEntry { padding-left: 7.5ex }   .SIndent5 .SDescription { padding-left: 9.5ex }\r
+\r
+    .SDescription a { color: #800000}\r
+    .SDescription a:active { color: #A00000 }\r
+\r
+    .SGroup td {\r
+        padding-top: .5em; padding-bottom: .25em }\r
+\r
+    .SGroup .SEntry {\r
+        font-weight: bold; font-variant: small-caps }\r
+\r
+    .SGroup .SEntry a { color: #800000 }\r
+    .SGroup .SEntry a:active { color: #F00000 }\r
+\r
+\r
+    .SMain td,\r
+    .SClass td,\r
+    .SDatabase td,\r
+    .SDatabaseTable td,\r
+    .SSection td {\r
+        font-size: 10pt;\r
+        padding-bottom: .25em }\r
+\r
+    .SClass td,\r
+    .SDatabase td,\r
+    .SDatabaseTable td,\r
+    .SSection td {\r
+        padding-top: 1em }\r
+\r
+    .SMain .SEntry,\r
+    .SClass .SEntry,\r
+    .SDatabase .SEntry,\r
+    .SDatabaseTable .SEntry,\r
+    .SSection .SEntry {\r
+        font-weight: bold;\r
+        }\r
+\r
+    .SMain .SEntry a,\r
+    .SClass .SEntry a,\r
+    .SDatabase .SEntry a,\r
+    .SDatabaseTable .SEntry a,\r
+    .SSection .SEntry a { color: #000000 }\r
+\r
+    .SMain .SEntry a:active,\r
+    .SClass .SEntry a:active,\r
+    .SDatabase .SEntry a:active,\r
+    .SDatabaseTable .SEntry a:active,\r
+    .SSection .SEntry a:active { color: #A00000 }\r
+\r
+\r
+\r
+\r
+\r
+.ClassHierarchy {\r
+    margin: 0 15px 1em 15px }\r
+\r
+    .CHEntry {\r
+        border-width: 1px 2px 2px 1px; border-style: solid; border-color: #A0A0A0;\r
+        margin-bottom: 3px;\r
+        padding: 2px 2ex;\r
+        font-size: 10pt;\r
+        background-color: #F4F4F4; color: #606060;\r
+        }\r
+\r
+    .Firefox .CHEntry {\r
+        -moz-border-radius: 4px;\r
+        }\r
+\r
+    .CHCurrent .CHEntry {\r
+        font-weight: bold;\r
+        border-color: #000000;\r
+        color: #000000;\r
+        }\r
+\r
+    .CHChildNote .CHEntry {\r
+        font-style: italic;\r
+        font-size: 8pt;\r
+        }\r
+\r
+    .CHIndent {\r
+        margin-left: 3ex;\r
+        }\r
+\r
+    .CHEntry a:link,\r
+    .CHEntry a:visited,\r
+    .CHEntry a:hover {\r
+        color: #606060;\r
+        }\r
+    .CHEntry a:active {\r
+        color: #800000;\r
+        }\r
+\r
+\r
+\r
+\r
+\r
+#Index {\r
+    background-color: #FFFFFF;\r
+    }\r
+\r
+/*  As opposed to .PopupSearchResultsPage #Index  */\r
+.IndexPage #Index,\r
+.FramedIndexPage #Index,\r
+.FramedSearchResultsPage #Index {\r
+    padding: 15px;\r
+    }\r
+\r
+.IndexPage #Index {\r
+    border-width: 0 0 1px 1px;\r
+    border-style: solid;\r
+    border-color: #000000;\r
+    font-size: 9pt;  /* To make 27ex match the menu's 27ex. */\r
+    margin-left: 27ex;\r
+    }\r
+\r
+\r
+    .IPageTitle {\r
+        font-size: 20pt; font-weight: bold;\r
+        color: #FFFFFF; background-color: #7070C0;\r
+        padding: 10px 15px 10px 15px;\r
+        border-width: 0 0 3px 0; border-color: #000000; border-style: solid;\r
+        margin: -15px -15px 0 -15px }\r
+\r
+    .FramedSearchResultsPage .IPageTitle {\r
+        margin-bottom: 15px;\r
+        }\r
+\r
+    .INavigationBar {\r
+        font-size: 10pt;\r
+        text-align: center;\r
+        background-color: #FFFFF0;\r
+        padding: 5px;\r
+        border-bottom: solid 1px black;\r
+        margin: 0 -15px 15px -15px;\r
+        }\r
+\r
+    .INavigationBar a {\r
+        font-weight: bold }\r
+\r
+    .IHeading {\r
+        font-size: 16pt; font-weight: bold;\r
+        padding: 2.5em 0 .5em 0;\r
+        text-align: center;\r
+        width: 3.5ex;\r
+        }\r
+    #IFirstHeading {\r
+        padding-top: 0;\r
+        }\r
+\r
+    .IEntry {\r
+        font-size: 10pt;\r
+        padding-left: 1ex;\r
+        }\r
+    .PopupSearchResultsPage .IEntry {\r
+        font-size: 8pt;\r
+        padding: 1px 5px;\r
+        }\r
+    .PopupSearchResultsPage .Opera9 .IEntry,\r
+    .FramedSearchResultsPage .Opera9 .IEntry {\r
+        text-align: left;\r
+        }\r
+    .FramedSearchResultsPage .IEntry {\r
+        padding: 0;\r
+        }\r
+\r
+    .ISubIndex {\r
+        padding-left: 3ex; padding-bottom: .5em }\r
+    .PopupSearchResultsPage .ISubIndex {\r
+        display: none;\r
+        }\r
+\r
+    /*  While it may cause some entries to look like links when they aren't, I found it's much easier to read the\r
+         index if everything's the same color.  */\r
+    .ISymbol {\r
+        font-weight: bold; color: #900000  }\r
+\r
+    .IndexPage .ISymbolPrefix,\r
+    .FramedIndexPage .ISymbolPrefix {\r
+        font-size: 10pt;\r
+        text-align: right;\r
+        color: #C47C7C;\r
+        background-color: #F8F8F8;\r
+        border-right: 3px solid #E0E0E0;\r
+        border-left: 1px solid #E0E0E0;\r
+        padding: 0 1px 0 2px;\r
+        }\r
+    .PopupSearchResultsPage .ISymbolPrefix,\r
+    .FramedSearchResultsPage .ISymbolPrefix {\r
+        color: #900000;\r
+        }\r
+    .PopupSearchResultsPage .ISymbolPrefix {\r
+        font-size: 8pt;\r
+        }\r
+\r
+    .IndexPage #IFirstSymbolPrefix,\r
+    .FramedIndexPage #IFirstSymbolPrefix {\r
+        border-top: 1px solid #E0E0E0;\r
+        }\r
+    .IndexPage #ILastSymbolPrefix,\r
+    .FramedIndexPage #ILastSymbolPrefix {\r
+        border-bottom: 1px solid #E0E0E0;\r
+        }\r
+    .IndexPage #IOnlySymbolPrefix,\r
+    .FramedIndexPage #IOnlySymbolPrefix {\r
+        border-top: 1px solid #E0E0E0;\r
+        border-bottom: 1px solid #E0E0E0;\r
+        }\r
+\r
+    a.IParent,\r
+    a.IFile {\r
+        display: block;\r
+        }\r
+\r
+    .PopupSearchResultsPage .SRStatus {\r
+        padding: 2px 5px;\r
+        font-size: 8pt;\r
+        font-style: italic;\r
+        }\r
+    .FramedSearchResultsPage .SRStatus {\r
+        font-size: 10pt;\r
+        font-style: italic;\r
+        }\r
+\r
+    .SRResult {\r
+        display: none;\r
+        }\r
+\r
+\r
+\r
+#Footer {\r
+    font-size: 8pt;\r
+    color: #989898;\r
+    text-align: right;\r
+    }\r
+\r
+#Footer p {\r
+    text-indent: 0;\r
+    margin-bottom: .5em;\r
+    }\r
+\r
+.ContentPage #Footer,\r
+.IndexPage #Footer {\r
+    text-align: right;\r
+    margin: 2px;\r
+    }\r
+\r
+.FramedMenuPage #Footer {\r
+    text-align: center;\r
+    margin: 5em 10px 10px 10px;\r
+    padding-top: 1em;\r
+    border-top: 1px solid #C8C8C8;\r
+    }\r
+\r
+    #Footer a:link,\r
+    #Footer a:hover,\r
+    #Footer a:visited { color: #989898 }\r
+    #Footer a:active { color: #A00000 }\r
+\r
diff --git a/docs/html/styles/2.css b/docs/html/styles/2.css
new file mode 100644 (file)
index 0000000..cea2729
--- /dev/null
@@ -0,0 +1,7 @@
+/*
+ * Use blank line between paragraphs instead of indenting the first line.
+ */
+p {
+    text-indent: 0;
+    margin-bottom: 1em;
+  }
diff --git a/docs/html/styles/main.css b/docs/html/styles/main.css
new file mode 100644 (file)
index 0000000..a672a94
--- /dev/null
@@ -0,0 +1,2 @@
+@import URL("1.css");
+@import URL("2.css");
diff --git a/docs/naturaldocs/CustomStyle.css b/docs/naturaldocs/CustomStyle.css
new file mode 100644 (file)
index 0000000..cea2729
--- /dev/null
@@ -0,0 +1,7 @@
+/*
+ * Use blank line between paragraphs instead of indenting the first line.
+ */
+p {
+    text-indent: 0;
+    margin-bottom: 1em;
+  }
diff --git a/docs/naturaldocs/Languages.txt b/docs/naturaldocs/Languages.txt
new file mode 100644 (file)
index 0000000..be96913
--- /dev/null
@@ -0,0 +1,113 @@
+Format: 1.4
+
+# This is the Natural Docs languages file for this project.  If you change
+# anything here, it will apply to THIS PROJECT ONLY.  If you'd like to change
+# something for all your projects, edit the Languages.txt in Natural Docs'
+# Config directory instead.
+
+
+# You can prevent certain file extensions from being scanned like this:
+# Ignore Extensions: [extension] [extension] ...
+
+
+#-------------------------------------------------------------------------------
+# SYNTAX:
+#
+# Unlike other Natural Docs configuration files, in this file all comments
+# MUST be alone on a line.  Some languages deal with the # character, so you
+# cannot put comments on the same line as content.
+#
+# Also, all lists are separated with spaces, not commas, again because some
+# languages may need to use them.
+#
+# Language: [name]
+# Alter Language: [name]
+#    Defines a new language or alters an existing one.  Its name can use any
+#    characters.  If any of the properties below have an add/replace form, you
+#    must use that when using Alter Language.
+#
+#    The language Shebang Script is special.  It's entry is only used for
+#    extensions, and files with those extensions have their shebang (#!) lines
+#    read to determine the real language of the file.  Extensionless files are
+#    always treated this way.
+#
+#    The language Text File is also special.  It's treated as one big comment
+#    so you can put Natural Docs content in them without special symbols.  Also,
+#    if you don't specify a package separator, ignored prefixes, or enum value
+#    behavior, it will copy those settings from the language that is used most
+#    in the source tree.
+#
+# Extensions: [extension] [extension] ...
+# [Add/Replace] Extensions: [extension] [extension] ...
+#    Defines the file extensions of the language's source files.  You can
+#    redefine extensions found in the main languages file.  You can use * to
+#    mean any undefined extension.
+#
+# Shebang Strings: [string] [string] ...
+# [Add/Replace] Shebang Strings: [string] [string] ...
+#    Defines a list of strings that can appear in the shebang (#!) line to
+#    designate that it's part of the language.  You can redefine strings found
+#    in the main languages file.
+#
+# Ignore Prefixes in Index: [prefix] [prefix] ...
+# [Add/Replace] Ignored Prefixes in Index: [prefix] [prefix] ...
+#
+# Ignore [Topic Type] Prefixes in Index: [prefix] [prefix] ...
+# [Add/Replace] Ignored [Topic Type] Prefixes in Index: [prefix] [prefix] ...
+#    Specifies prefixes that should be ignored when sorting symbols in an
+#    index.  Can be specified in general or for a specific topic type.
+#
+#------------------------------------------------------------------------------
+# For basic language support only:
+#
+# Line Comments: [symbol] [symbol] ...
+#    Defines a space-separated list of symbols that are used for line comments,
+#    if any.
+#
+# Block Comments: [opening sym] [closing sym] [opening sym] [closing sym] ...
+#    Defines a space-separated list of symbol pairs that are used for block
+#    comments, if any.
+#
+# Package Separator: [symbol]
+#    Defines the default package separator symbol.  The default is a dot.
+#
+# [Topic Type] Prototype Enders: [symbol] [symbol] ...
+#    When defined, Natural Docs will attempt to get a prototype from the code
+#    immediately following the topic type.  It stops when it reaches one of
+#    these symbols.  Use \n for line breaks.
+#
+# Line Extender: [symbol]
+#    Defines the symbol that allows a prototype to span multiple lines if
+#    normally a line break would end it.
+#
+# Enum Values: [global|under type|under parent]
+#    Defines how enum values are referenced.  The default is global.
+#    global       - Values are always global, referenced as 'value'.
+#    under type   - Values are under the enum type, referenced as
+#               'package.enum.value'.
+#    under parent - Values are under the enum's parent, referenced as
+#               'package.value'.
+#
+# Perl Package: [perl package]
+#    Specifies the Perl package used to fine-tune the language behavior in ways
+#    too complex to do in this file.
+#
+#------------------------------------------------------------------------------
+# For full language support only:
+#
+# Full Language Support: [perl package]
+#    Specifies the Perl package that has the parsing routines necessary for full
+#    language support.
+#
+#-------------------------------------------------------------------------------
+
+# The following languages are defined in the main file, if you'd like to alter
+# them:
+#
+#    Text File, Shebang Script, C/C++, C#, Java, JavaScript, Perl, Python,
+#    PHP, SQL, Visual Basic, Pascal, Assembly, Ada, Tcl, Ruby, Makefile,
+#    ActionScript, ColdFusion, R, Fortran
+
+# If you add a language that you think would be useful to other developers
+# and should be included in Natural Docs by default, please e-mail it to
+# languages [at] naturaldocs [dot] org.
diff --git a/docs/naturaldocs/Menu.txt b/docs/naturaldocs/Menu.txt
new file mode 100644 (file)
index 0000000..0a4eadf
--- /dev/null
@@ -0,0 +1,59 @@
+Format: 1.4
+
+
+Title: ALURE
+SubTitle: API Reference
+
+# You can add a footer to your documentation like this:
+# Footer: [text]
+# If you want to add a copyright notice, this would be the place to do it.
+
+# You can add a timestamp to your documentation like one of these:
+# Timestamp: Generated on month day, year
+# Timestamp: Updated mm/dd/yyyy
+# Timestamp: Last updated mon day
+#
+#   m     - One or two digit month.  January is "1"
+#   mm    - Always two digit month.  January is "01"
+#   mon   - Short month word.  January is "Jan"
+#   month - Long month word.  January is "January"
+#   d     - One or two digit day.  1 is "1"
+#   dd    - Always two digit day.  1 is "01"
+#   day   - Day with letter extension.  1 is "1st"
+#   yy    - Two digit year.  2006 is "06"
+#   yyyy  - Four digit year.  2006 is "2006"
+#   year  - Four digit year.  2006 is "2006"
+
+
+# --------------------------------------------------------------------------
+# 
+# Cut and paste the lines below to change the order in which your files
+# appear on the menu.  Don't worry about adding or removing files, Natural
+# Docs will take care of that.
+# 
+# You can further organize the menu by grouping the entries.  Add a
+# "Group: [name] {" line to start a group, and add a "}" to end it.
+# 
+# You can add text and web links to the menu by adding "Text: [text]" and
+# "Link: [name] ([URL])" lines, respectively.
+# 
+# The formatting and comments are auto-generated, so don't worry about
+# neatness when editing the file.  Natural Docs will clean it up the next
+# time it is run.  When working with groups, just deal with the braces and
+# forget about the indentation and comments.
+# 
+# --------------------------------------------------------------------------
+
+
+File: Main and Miscellanious  (no auto-title, alure.cpp)
+File: File Loading  (no auto-title, buffer.cpp)
+File: Streaming  (no auto-title, stream.cpp)
+File: File I/O  (istream.cpp)
+File: Automatic Playback  (streamplay.cpp)
+
+Group: Index  {
+
+   Index: Everything
+   Function Index: Functions
+   }  # Group: Index
+
diff --git a/docs/naturaldocs/Topics.txt b/docs/naturaldocs/Topics.txt
new file mode 100644 (file)
index 0000000..b1a9b93
--- /dev/null
@@ -0,0 +1,81 @@
+Format: 1.4
+
+# This is the Natural Docs topics file for this project.  If you change anything
+# here, it will apply to THIS PROJECT ONLY.  If you'd like to change something
+# for all your projects, edit the Topics.txt in Natural Docs' Config directory
+# instead.
+
+
+# If you'd like to prevent keywords from being recognized by Natural Docs, you
+# can do it like this:
+# Ignore Keywords: [keyword], [keyword], ...
+#
+# Or you can use the list syntax like how they are defined:
+# Ignore Keywords:
+#    [keyword]
+#    [keyword], [plural keyword]
+#    ...
+
+
+#-------------------------------------------------------------------------------
+# SYNTAX:
+#
+# Topic Type: [name]
+# Alter Topic Type: [name]
+#    Creates a new topic type or alters one from the main file.  Each type gets
+#    its own index and behavior settings.  Its name can have letters, numbers,
+#    spaces, and these charaters: - / . '
+#
+# Plural: [name]
+#    Sets the plural name of the topic type, if different.
+#
+# Keywords:
+#    [keyword]
+#    [keyword], [plural keyword]
+#    ...
+#    Defines or adds to the list of keywords for the topic type.  They may only
+#    contain letters, numbers, and spaces and are not case sensitive.  Plural
+#    keywords are used for list topics.  You can redefine keywords found in the
+#    main topics file.
+#
+# Index: [yes|no]
+#    Whether the topics get their own index.  Defaults to yes.  Everything is
+#    included in the general index regardless of this setting.
+#
+# Scope: [normal|start|end|always global]
+#    How the topics affects scope.  Defaults to normal.
+#    normal        - Topics stay within the current scope.
+#    start         - Topics start a new scope for all the topics beneath it,
+#                    like class topics.
+#    end           - Topics reset the scope back to global for all the topics
+#                    beneath it.
+#    always global - Topics are defined as global, but do not change the scope
+#                    for any other topics.
+#
+# Class Hierarchy: [yes|no]
+#    Whether the topics are part of the class hierarchy.  Defaults to no.
+#
+# Page Title If First: [yes|no]
+#    Whether the topic's title becomes the page title if it's the first one in
+#    a file.  Defaults to no.
+#
+# Break Lists: [yes|no]
+#    Whether list topics should be broken into individual topics in the output.
+#    Defaults to no.
+#
+# Can Group With: [type], [type], ...
+#    Defines a list of topic types that this one can possibly be grouped with.
+#    Defaults to none.
+#-------------------------------------------------------------------------------
+
+# The following topics are defined in the main file, if you'd like to alter
+# their behavior or add keywords:
+#
+#    Generic, Class, Interface, Section, File, Group, Function, Variable,
+#    Property, Type, Constant, Enumeration, Event, Delegate, Macro,
+#    Database, Database Table, Database View, Database Index, Database
+#    Cursor, Database Trigger, Cookie, Build Target
+
+# If you add something that you think would be useful to other developers
+# and should be included in Natural Docs by default, please e-mail it to
+# topics [at] naturaldocs [dot] org.
diff --git a/examples/alurecdplay.c b/examples/alurecdplay.c
new file mode 100644 (file)
index 0000000..427f359
--- /dev/null
@@ -0,0 +1,382 @@
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "AL/alure.h"
+
+#ifdef __linux__
+/* Linux implementation for reading CD digital audio */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <linux/cdrom.h>
+
+
+typedef struct {
+    int fd;
+    int start;
+    int current;
+    int end;
+} CDDAData;
+
+static const char *cd_device = "/dev/cdrom1";
+
+static void *cdda_open_file(const char *fname)
+{
+    struct cdrom_tochdr cdtochdr;
+    struct cdrom_tocentry cdtocentry;
+    int startaddr=-1, endaddr=-1, idx;
+    CDDAData *dat;
+    int fd, ret;
+
+    /* Make sure the filename has the appropriate URI and extract the track
+     * number */
+    if(strncmp(fname, "cdda://", 7) != 0)
+        return NULL;
+    idx = atoi(fname+7);
+
+    /* Open the block device and get the TOC header */
+    fd = open(cd_device, O_RDONLY | O_NONBLOCK);
+    if(fd == -1) return NULL;
+
+    ret = ioctl(fd, CDROMREADTOCHDR, &cdtochdr);
+    if(ret != -1)
+    {
+        if(idx < cdtochdr.cdth_trk0 || idx >= cdtochdr.cdth_trk1)
+            ret = -1;
+    }
+    if(ret != -1)
+    {
+        /* Get the start address for the requested track, and the start address
+         * of the next track as the end point */
+        cdtocentry.cdte_format = CDROM_LBA;
+        cdtocentry.cdte_track = idx;
+        ret = ioctl(fd, CDROMREADTOCENTRY, &cdtocentry);
+        if(ret != -1 && !(cdtocentry.cdte_ctrl&CDROM_DATA_TRACK))
+            startaddr = cdtocentry.cdte_addr.lba;
+    }
+    if(ret != -1)
+    {
+        cdtocentry.cdte_format = CDROM_LBA;
+        cdtocentry.cdte_track = ++idx;
+        ret = ioctl(fd, CDROMREADTOCENTRY, &cdtocentry);
+        if(ret != -1)
+            endaddr = cdtocentry.cdte_addr.lba;
+    }
+
+    if(ret == -1 || startaddr == -1 || endaddr == -1)
+    {
+        close(fd);
+        return NULL;
+    }
+
+    dat = malloc(sizeof(*dat));
+    dat->fd = fd;
+    dat->start = startaddr;
+    dat->current = startaddr;
+    dat->end = endaddr;
+
+    return dat;
+}
+
+static ALboolean cdda_get_format(void *instance, ALenum *format, ALuint *samplerate, ALuint *blocksize)
+{
+    /* These values are specified by the red-book audio standard and do not
+     * change */
+    *format = AL_FORMAT_STEREO16;
+    *samplerate = 44100;
+    *blocksize = CD_FRAMESIZE_RAW;
+
+    return AL_TRUE;
+    (void)instance;
+}
+
+static ALuint cdda_decode(void *instance, ALubyte *data, ALuint bytes)
+{
+    CDDAData *self = instance;
+
+    ALuint got = 0;
+    while(bytes-got >= CD_FRAMESIZE_RAW && self->current < self->end)
+    {
+        struct cdrom_read_audio cdra;
+
+        /* Read as many frames that are left that will fit */
+        cdra.addr.lba = self->current;
+        cdra.addr_format = CDROM_LBA;
+        cdra.nframes = (bytes-got) / CD_FRAMESIZE_RAW;
+        cdra.buf = data;
+
+        if(cdra.nframes > self->end-self->current)
+            cdra.nframes = self->end-self->current;
+
+        if(ioctl(self->fd, CDROMREADAUDIO, &cdra) == -1)
+        {
+            cdra.nframes = 1;
+            memset(cdra.buf, 0, CD_FRAMESIZE_RAW);
+        }
+
+        self->current += cdra.nframes;
+        data += CD_FRAMESIZE_RAW*cdra.nframes;
+        got += CD_FRAMESIZE_RAW*cdra.nframes;
+    }
+
+    return got;
+}
+
+static ALboolean cdda_rewind(void *instance)
+{
+    CDDAData *self = instance;
+
+    self->current = self->start;
+    return AL_TRUE;
+}
+
+static void cdda_close(void *instance)
+{
+    CDDAData *self = instance;
+
+    close(self->fd);
+    free(self);
+}
+
+#elif defined(HAVE_DDK_NTDDCDRM_H)
+/* Windows implementation for reading CD digital audio */
+#include <windows.h>
+#include <ddk/ntddcdrm.h>
+
+/* Defined by red-book standard; do not change! */
+#define CD_FRAMESIZE_RAW  (2352)
+
+#define CDFRAMES_PERSEC  (75)
+#define CDFRAMES_PERMIN  (CDFRAMES_PERSEC * 60)
+#define FRAME_OF_ADDR(a) ((a)[1] * CDFRAMES_PERMIN + (a)[2] * CDFRAMES_PERSEC + (a)[3])
+#define FRAME_OF_TOC(toc, idx)  FRAME_OF_ADDR((toc).TrackData[idx - (toc).FirstTrack].Address)
+
+/* All of this is pretty similar to the Linux version, except using the WinAPI
+ * device functions instead of POSIX */
+typedef struct {
+    HANDLE fd;
+    DWORD start;
+    DWORD current;
+    DWORD end;
+} CDDAData;
+
+static const char *cd_device = "D";
+
+static void *cdda_open_file(const char *fname)
+{
+    /* Device filename is of the format "\\.\D:", where "D" is the letter of
+     * the CD drive */
+    const char cd_drv[] = { '\\','\\','.','\\',*cd_device,':', 0 };
+    DWORD br, idx;
+    CDROM_TOC toc;
+    CDDAData *dat;
+    HANDLE fd;
+    int ret;
+
+    if(strncmp(fname, "cdda://", 7) != 0)
+        return NULL;
+    idx = atoi(fname+7);
+
+    fd = CreateFileA(cd_drv, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
+    if(fd == (HANDLE)-1) return NULL;
+
+    ret = DeviceIoControl(fd, IOCTL_CDROM_READ_TOC, NULL, 0,
+                          &toc, sizeof(toc), &br, NULL);
+    if(ret == 0 || idx < toc.FirstTrack || idx > toc.LastTrack ||
+       (toc.TrackData[idx-toc.FirstTrack].Control&4))
+    {
+        CloseHandle(fd);
+        return NULL;
+    }
+
+    dat = malloc(sizeof(*dat));
+    dat->fd = fd;
+    dat->start = FRAME_OF_TOC(toc, idx) - FRAME_OF_TOC(toc, toc.FirstTrack);
+    dat->current = dat->start;
+    dat->end = FRAME_OF_TOC(toc, idx+1) - FRAME_OF_TOC(toc, toc.FirstTrack);
+
+    return dat;
+}
+
+static ALboolean cdda_get_format(void *instance, ALenum *format, ALuint *samplerate, ALuint *blocksize)
+{
+    *format = AL_FORMAT_STEREO16;
+    *samplerate = 44100;
+    *blocksize = CD_FRAMESIZE_RAW;
+
+    return AL_TRUE;
+    (void)instance;
+}
+
+static ALuint cdda_decode(void *instance, ALubyte *data, ALuint bytes)
+{
+    CDDAData *self = instance;
+
+    ALuint got = 0;
+    while(bytes-got >= CD_FRAMESIZE_RAW && self->current < self->end)
+    {
+        RAW_READ_INFO rdInfo;
+        DWORD br;
+
+        rdInfo.DiskOffset.QuadPart = (LONGLONG)self->current<<11;
+        rdInfo.SectorCount = (bytes-got) / CD_FRAMESIZE_RAW;
+        rdInfo.TrackMode = CDDA;
+
+        if(rdInfo.SectorCount > self->end-self->current)
+            rdInfo.SectorCount = self->end-self->current;
+
+        if(!DeviceIoControl(self->fd, IOCTL_CDROM_RAW_READ,
+                            &rdInfo, sizeof(rdInfo), data, bytes-got,
+                            &br, NULL))
+        {
+            rdInfo.SectorCount = 1;
+            memset(data, 0, CD_FRAMESIZE_RAW);
+        }
+
+        self->current += rdInfo.SectorCount;
+        data += CD_FRAMESIZE_RAW*rdInfo.SectorCount;
+        got += CD_FRAMESIZE_RAW*rdInfo.SectorCount;
+    }
+
+    return got;
+}
+
+static ALboolean cdda_rewind(void *instance)
+{
+    CDDAData *self = instance;
+
+    self->current = self->start;
+    return AL_TRUE;
+}
+
+static void cdda_close(void *instance)
+{
+    CDDAData *self = instance;
+
+    CloseHandle(self->fd);
+    free(self);
+}
+
+#else
+
+static const char *cd_device = "(unknown)";
+
+static void *cdda_open_file(const char *fname)
+{
+    if(strncmp(fname, "cdda://", 7) == 0)
+        fprintf(stderr, "CD Digital Audio was not compiled for this system\n");
+    return NULL;
+}
+
+static ALboolean cdda_get_format(void *instance, ALenum *format, ALuint *samplerate, ALuint *blocksize)
+{
+    return AL_FALSE;
+    (void)instance;
+}
+
+static ALuint cdda_decode(void *instance, ALubyte *data, ALuint bytes)
+{
+    return 0;
+    (void)instance;
+    (void)data;
+    (void)bytes;
+}
+
+static ALboolean cdda_rewind(void *instance)
+{
+    return AL_FALSE;
+    (void)instance;
+}
+
+static void cdda_close(void *instance)
+{
+    (void)instance;
+}
+
+#endif
+
+
+static void eos_callback(void *param, ALuint unused)
+{
+    *(volatile int*)param = 1;
+    (void)unused;
+}
+
+#define NUM_BUFS 3
+
+
+int main(int argc, char **argv)
+{
+    volatile int isdone;
+    alureStream *stream;
+    const char *fname;
+    ALuint src;
+
+    if(argc < 2 || (strcmp(argv[1], "-cd-device") == 0 && argc < 4))
+    {
+        fprintf(stderr, "Usage %s [-cd-device <device>] cdda://<tracknum>\n", argv[0]);
+        fprintf(stderr, "Default CD device is %s\n", cd_device);
+        return 1;
+    }
+
+    if(strcmp(argv[1], "-cd-device") != 0)
+        fname = argv[1];
+    else
+    {
+        cd_device = argv[2];
+        fname = argv[3];
+    }
+
+    alureInstallDecodeCallbacks(-1, cdda_open_file, NULL, cdda_get_format,
+                                cdda_decode, cdda_rewind, cdda_close);
+
+    if(!alureInitDevice(NULL, NULL))
+    {
+        fprintf(stderr, "Failed to open OpenAL device: %s\n", alureGetErrorString());
+        return 1;
+    }
+
+    alGenSources(1, &src);
+    if(alGetError() != AL_NO_ERROR)
+    {
+        fprintf(stderr, "Failed to create OpenAL source!\n");
+        alureShutdownDevice();
+        return 1;
+    }
+
+    alureStreamSizeIsMicroSec(AL_TRUE);
+
+    stream = alureCreateStreamFromFile(fname, 250000, 0, NULL);
+    if(!stream)
+    {
+        fprintf(stderr, "Could not load %s: %s\n", fname, alureGetErrorString());
+        alDeleteSources(1, &src);
+
+        alureShutdownDevice();
+        return 1;
+    }
+
+    isdone = 0;
+    if(!alurePlaySourceStream(src, stream, NUM_BUFS, 0, eos_callback, (void*)&isdone))
+    {
+        fprintf(stderr, "Failed to play stream: %s\n", alureGetErrorString());
+        isdone = 1;
+    }
+
+    while(!isdone)
+    {
+        alureSleep(0.125);
+        alureUpdate();
+    }
+    alureStopSource(src, AL_FALSE);
+
+    alDeleteSources(1, &src);
+    alureDestroyStream(stream, 0, NULL);
+
+    alureShutdownDevice();
+    return 0;
+}
diff --git a/examples/alureplay.c b/examples/alureplay.c
new file mode 100644 (file)
index 0000000..03a99ec
--- /dev/null
@@ -0,0 +1,69 @@
+#include <stdio.h>
+
+#include "AL/alure.h"
+
+volatile int isdone = 0;
+static void eos_callback(void *unused, ALuint unused2)
+{
+    isdone = 1;
+    (void)unused;
+    (void)unused2;
+}
+
+int main( int argc, char **argv)
+{
+    ALuint src, buf;
+
+    if(argc < 2)
+    {
+        fprintf(stderr, "Usage %s <soundfile>\n", argv[0]);
+        return 1;
+    }
+
+    if(!alureInitDevice(NULL, NULL))
+    {
+        fprintf(stderr, "Failed to open OpenAL device: %s\n", alureGetErrorString());
+        return 1;
+    }
+
+    alGenSources(1, &src);
+    if(alGetError() != AL_NO_ERROR)
+    {
+        fprintf(stderr, "Failed to create OpenAL source!\n");
+        alureShutdownDevice();
+        return 1;
+    }
+
+    buf = alureCreateBufferFromFile(argv[1]);
+    if(!buf)
+    {
+        fprintf(stderr, "Could not load %s: %s\n", argv[1], alureGetErrorString());
+        alDeleteSources(1, &src);
+
+        alureShutdownDevice();
+        return 1;
+    }
+
+    alSourcei(src, AL_BUFFER, buf);
+    if(alurePlaySource(src, eos_callback, NULL) == AL_FALSE)
+    {
+        fprintf(stderr, "Failed to start source!\n");
+        alDeleteSources(1, &src);
+        alDeleteBuffers(1, &buf);
+
+        alureShutdownDevice();
+        return 1;
+    }
+
+    while(!isdone)
+    {
+        alureSleep(0.125);
+        alureUpdate();
+    }
+
+    alDeleteSources(1, &src);
+    alDeleteBuffers(1, &buf);
+
+    alureShutdownDevice();
+    return 0;
+}
diff --git a/examples/alurestream.c b/examples/alurestream.c
new file mode 100644 (file)
index 0000000..b163dce
--- /dev/null
@@ -0,0 +1,70 @@
+#include <stdio.h>
+
+#include "AL/alure.h"
+
+volatile int isdone = 0;
+static void eos_callback(void *unused, ALuint unused2)
+{
+    isdone = 1;
+    (void)unused;
+    (void)unused2;
+}
+
+#define NUM_BUFS 3
+
+int main(int argc, char **argv)
+{
+    alureStream *stream;
+    ALuint src;
+
+    if(argc < 2)
+    {
+        fprintf(stderr, "Usage %s <soundfile>\n", argv[0]);
+        return 1;
+    }
+
+    if(!alureInitDevice(NULL, NULL))
+    {
+        fprintf(stderr, "Failed to open OpenAL device: %s\n", alureGetErrorString());
+        return 1;
+    }
+
+    alGenSources(1, &src);
+    if(alGetError() != AL_NO_ERROR)
+    {
+        fprintf(stderr, "Failed to create OpenAL source!\n");
+        alureShutdownDevice();
+        return 1;
+    }
+
+    alureStreamSizeIsMicroSec(AL_TRUE);
+
+    stream = alureCreateStreamFromFile(argv[1], 250000, 0, NULL);
+    if(!stream)
+    {
+        fprintf(stderr, "Could not load %s: %s\n", argv[1], alureGetErrorString());
+        alDeleteSources(1, &src);
+
+        alureShutdownDevice();
+        return 1;
+    }
+
+    if(!alurePlaySourceStream(src, stream, NUM_BUFS, 0, eos_callback, NULL))
+    {
+        fprintf(stderr, "Failed to play stream: %s\n", alureGetErrorString());
+        isdone = 1;
+    }
+
+    while(!isdone)
+    {
+        alureSleep(0.125);
+        alureUpdate();
+    }
+    alureStopSource(src, AL_FALSE);
+
+    alDeleteSources(1, &src);
+    alureDestroyStream(stream, 0, NULL);
+
+    alureShutdownDevice();
+    return 0;
+}
diff --git a/include/AL/alure.h b/include/AL/alure.h
new file mode 100644 (file)
index 0000000..8076f76
--- /dev/null
@@ -0,0 +1,156 @@
+#ifndef AL_ALURE_H
+#define AL_ALURE_H
+
+#if !defined(ALC_VERSION_0_1) || !defined(AL_VERSION_1_0)
+#ifdef _WIN32
+#include <al.h>
+#include <alc.h>
+#elif defined(__APPLE__)
+#include <OpenAL/alc.h>
+#include <OpenAL/al.h>
+#else
+#include <AL/al.h>
+#include <AL/alc.h>
+#endif
+#endif
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#define ALURE_VERSION_STRING "1.2"
+
+#define ALURE_VERSION_1_0
+#define ALURE_VERSION_1_1
+#define ALURE_VERSION_1_2
+
+
+#ifndef ALURE_API
+ #if defined(ALURE_STATIC_LIBRARY)
+  #define ALURE_API
+ #elif defined(_WIN32)
+  #define ALURE_API __declspec(dllimport)
+ #else
+  #define ALURE_API extern
+ #endif
+#endif
+
+#if defined(_WIN32)
+ #define ALURE_APIENTRY __cdecl
+
+ #include <sys/types.h>
+ typedef __int64 alureInt64;
+ typedef unsigned __int64 alureUInt64;
+#else
+ #define ALURE_APIENTRY
+
+ #include <stdint.h>
+ typedef int64_t alureInt64;
+ typedef uint64_t alureUInt64;
+#endif
+
+typedef struct alureStream alureStream;
+
+ALURE_API void ALURE_APIENTRY alureGetVersion(ALuint *major, ALuint *minor);
+ALURE_API const ALchar* ALURE_APIENTRY alureGetErrorString(void);
+
+ALURE_API const ALCchar** ALURE_APIENTRY alureGetDeviceNames(ALCboolean all, ALCsizei *count);
+ALURE_API ALvoid ALURE_APIENTRY alureFreeDeviceNames(const ALCchar **names);
+
+ALURE_API ALboolean ALURE_APIENTRY alureInitDevice(const ALCchar *name, const ALCint *attribs);
+ALURE_API ALboolean ALURE_APIENTRY alureShutdownDevice(void);
+
+ALURE_API ALenum ALURE_APIENTRY alureGetSampleFormat(ALuint channels, ALuint bits, ALuint floatbits);
+
+ALURE_API ALboolean ALURE_APIENTRY alureSleep(ALfloat duration);
+
+ALURE_API ALboolean ALURE_APIENTRY alureStreamSizeIsMicroSec(ALboolean useus);
+
+ALURE_API ALuint ALURE_APIENTRY alureCreateBufferFromFile(const ALchar *fname);
+ALURE_API ALuint ALURE_APIENTRY alureCreateBufferFromMemory(const ALubyte *data, ALsizei length);
+ALURE_API ALboolean ALURE_APIENTRY alureBufferDataFromFile(const ALchar *fname, ALuint buffer);
+ALURE_API ALboolean ALURE_APIENTRY alureBufferDataFromMemory(const ALubyte *fdata, ALsizei length, ALuint buffer);
+
+ALURE_API alureStream* ALURE_APIENTRY alureCreateStreamFromFile(const ALchar *fname, ALsizei chunkLength, ALsizei numBufs, ALuint *bufs);
+ALURE_API alureStream* ALURE_APIENTRY alureCreateStreamFromMemory(const ALubyte *data, ALuint length, ALsizei chunkLength, ALsizei numBufs, ALuint *bufs);
+ALURE_API alureStream* ALURE_APIENTRY alureCreateStreamFromStaticMemory(const ALubyte *data, ALuint length, ALsizei chunkLength, ALsizei numBufs, ALuint *bufs);
+ALURE_API alureStream* ALURE_APIENTRY alureCreateStreamFromCallback(
+    ALuint (*callback)(void *userdata, ALubyte *data, ALuint bytes),
+    void *userdata, ALenum format, ALuint samplerate,
+    ALsizei chunkLength, ALsizei numBufs, ALuint *bufs);
+ALURE_API alureInt64 ALURE_APIENTRY alureGetStreamLength(alureStream *stream);
+ALURE_API ALsizei ALURE_APIENTRY alureGetStreamFrequency(alureStream *stream);
+ALURE_API ALsizei ALURE_APIENTRY alureBufferDataFromStream(alureStream *stream, ALsizei numBufs, ALuint *bufs);
+ALURE_API ALboolean ALURE_APIENTRY alureRewindStream(alureStream *stream);
+ALURE_API ALboolean ALURE_APIENTRY alureSetStreamOrder(alureStream *stream, ALuint order);
+ALURE_API ALboolean ALURE_APIENTRY alureSetStreamPatchset(alureStream *stream, const ALchar *patchset);
+ALURE_API ALboolean ALURE_APIENTRY alureDestroyStream(alureStream *stream, ALsizei numBufs, ALuint *bufs);
+
+ALURE_API void ALURE_APIENTRY alureUpdate(void);
+ALURE_API ALboolean ALURE_APIENTRY alureUpdateInterval(ALfloat interval);
+
+ALURE_API ALboolean ALURE_APIENTRY alurePlaySourceStream(ALuint source,
+    alureStream *stream, ALsizei numBufs, ALsizei loopcount,
+    void (*eos_callback)(void *userdata, ALuint source), void *userdata);
+ALURE_API ALboolean ALURE_APIENTRY alurePlaySource(ALuint source,
+    void (*callback)(void *userdata, ALuint source), void *userdata);
+ALURE_API ALboolean ALURE_APIENTRY alureStopSource(ALuint source, ALboolean run_callback);
+ALURE_API ALboolean ALURE_APIENTRY alurePauseSource(ALuint source);
+ALURE_API ALboolean ALURE_APIENTRY alureResumeSource(ALuint source);
+
+ALURE_API ALboolean ALURE_APIENTRY alureInstallDecodeCallbacks(ALint index,
+    void*     (*open_file)(const ALchar*),
+    void*     (*open_mem)(const ALubyte*,ALuint),
+    ALboolean (*get_format)(void*,ALenum*,ALuint*,ALuint*),
+    ALuint    (*decode)(void*,ALubyte*,ALuint),
+    ALboolean (*rewind)(void*),
+    void      (*close)(void*));
+ALURE_API ALboolean ALURE_APIENTRY alureSetIOCallbacks(
+      void* (*open)(const char*,ALuint),
+      void (*close)(void*),
+      ALsizei (*read)(void*,ALubyte*,ALuint),
+      ALsizei (*write)(void*,const ALubyte*,ALuint),
+      alureInt64 (*seek)(void*,alureInt64,int));
+
+ALURE_API void* ALURE_APIENTRY alureGetProcAddress(const ALchar *funcname);
+
+typedef void            (ALURE_APIENTRY *LPALUREGETVERSION)(ALuint*,ALuint*);
+typedef const ALchar*   (ALURE_APIENTRY *LPALUREGETERRORSTRING)(void);
+typedef const ALCchar** (ALURE_APIENTRY *LPALUREGETDEVICENAMES)(ALCboolean,ALCsizei*);
+typedef ALvoid          (ALURE_APIENTRY *LPALUREFREEDEVICENAMES)(const ALCchar**);
+typedef ALboolean       (ALURE_APIENTRY *LPALUREINITDEVICE)(const ALCchar*,const ALCint*);
+typedef ALboolean       (ALURE_APIENTRY *LPALURESHUTDOWNDEVICE)(void);
+typedef ALenum          (ALURE_APIENTRY *LPALUREGETSAMPLEFORMAT)(ALuint,ALuint,ALuint);
+typedef ALboolean       (ALURE_APIENTRY *LPALURESLEEP)(ALfloat);
+typedef ALuint          (ALURE_APIENTRY *LPALURECREATEBUFFERFROMFILE)(const ALchar*);
+typedef ALuint          (ALURE_APIENTRY *LPALURECREATEBUFFERFROMMEMORY)(const ALubyte*,ALsizei);
+typedef ALboolean       (ALURE_APIENTRY *LPALUREBUFFERDATAFROMFILE)(const ALchar *fname, ALuint buffer);
+typedef ALboolean       (ALURE_APIENTRY *LPALUREBUFFERDATAFROMMEMORY)(const ALubyte *fdata, ALsizei length, ALuint buffer);
+typedef ALboolean       (ALURE_APIENTRY *LPALURESTREAMSIZEISMICROSEC)(ALboolean);
+typedef alureStream*    (ALURE_APIENTRY *LPALURECREATESTREAMFROMFILE)(const ALchar*,ALsizei,ALsizei,ALuint*);
+typedef alureStream*    (ALURE_APIENTRY *LPALURECREATESTREAMFROMMEMORY)(const ALubyte*,ALuint,ALsizei,ALsizei,ALuint*);
+typedef alureStream*    (ALURE_APIENTRY *LPALURECREATESTREAMFROMSTATICMEMORY)(const ALubyte*,ALuint,ALsizei,ALsizei,ALuint*);
+typedef alureStream*    (ALURE_APIENTRY *LPALURECREATESTREAMFROMCALLBACK)(ALuint(*)(void*,ALubyte*,ALuint),void*,ALenum,ALuint,ALsizei,ALsizei,ALuint*);
+typedef alureInt64      (ALURE_APIENTRY *LPALUREGETSTREAMLENGTH)(alureStream*);
+typedef ALsizei         (ALURE_APIENTRY *LPALUREGETSTREAMFREQUENCY)(alureStream*);
+typedef ALsizei         (ALURE_APIENTRY *LPALUREBUFFERDATAFROMSTREAM)(alureStream*,ALsizei,ALuint*);
+typedef ALboolean       (ALURE_APIENTRY *LPALUREREWINDSTREAM)(alureStream*);
+typedef ALboolean       (ALURE_APIENTRY *LPALURESETSTREAMORDER)(alureStream*,ALuint);
+typedef ALboolean       (ALURE_APIENTRY *LPALURESETSTREAMPATCHSET)(alureStream*,const ALchar*);
+typedef ALboolean       (ALURE_APIENTRY *LPALUREDESTROYSTREAM)(alureStream*,ALsizei,ALuint*);
+typedef void            (ALURE_APIENTRY *LPALUREUPDATE)(void);
+typedef ALboolean       (ALURE_APIENTRY *LPALUREUPDATEINTERVAL)(ALfloat);
+typedef ALboolean       (ALURE_APIENTRY *LPALUREPLAYSOURCESTREAM)(ALuint,alureStream*,ALsizei,ALsizei,void(*)(void*,ALuint),void*);
+typedef ALboolean       (ALURE_APIENTRY *LPALUREPLAYSOURCE)(ALuint,void(*)(void*,ALuint),void*);
+typedef ALboolean       (ALURE_APIENTRY *LPALURESTOPSOURCE)(ALuint,ALboolean);
+typedef ALboolean       (ALURE_APIENTRY *LPALUREPAUSESOURCE)(ALuint);
+typedef ALboolean       (ALURE_APIENTRY *LPALURERESUMESOURCE)(ALuint);
+typedef ALboolean       (ALURE_APIENTRY *LPALUREINSTALLDECODECALLBACKS)(ALint,void*(*)(const char*),void*(*)(const ALubyte*,ALuint),ALboolean(*)(void*,ALenum*,ALuint*,ALuint*),ALuint(*)(void*,ALubyte*,ALuint),ALboolean(*)(void*),void(*)(void*));
+typedef ALboolean       (ALURE_APIENTRY *LPALURESETIOCALLBACKS)(void*(*)(const char*,ALuint),void(*)(void*),ALsizei(*)(void*,ALubyte*,ALuint),ALsizei(*)(void*,const ALubyte*,ALuint),alureInt64(*)(void*,alureInt64,int));
+typedef void*           (ALURE_APIENTRY *LPALUREGETPROCADDRESS)(const ALchar*);
+
+#if defined(__cplusplus)
+}  /* extern "C" */
+#endif
+
+#endif /* AL_ALURE_H */
diff --git a/include/alext.h b/include/alext.h
new file mode 100644 (file)
index 0000000..a32dd29
--- /dev/null
@@ -0,0 +1,101 @@
+#ifndef AL_ALEXT_H
+#define AL_ALEXT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef AL_LOKI_IMA_ADPCM_format
+#define AL_LOKI_IMA_ADPCM_format 1
+#define AL_FORMAT_IMA_ADPCM_MONO16_EXT           0x10000
+#define AL_FORMAT_IMA_ADPCM_STEREO16_EXT         0x10001
+#endif
+
+#ifndef AL_LOKI_WAVE_format
+#define AL_LOKI_WAVE_format 1
+#define AL_FORMAT_WAVE_EXT                       0x10002
+#endif
+
+#ifndef AL_EXT_vorbis
+#define AL_EXT_vorbis 1
+#define AL_FORMAT_VORBIS_EXT                     0x10003
+#endif
+
+#ifndef AL_LOKI_quadriphonic
+#define AL_LOKI_quadriphonic 1
+#define AL_FORMAT_QUAD8_LOKI                     0x10004
+#define AL_FORMAT_QUAD16_LOKI                    0x10005
+#endif
+
+#ifndef AL_EXT_float32
+#define AL_EXT_float32 1
+#define AL_FORMAT_MONO_FLOAT32                   0x10010
+#define AL_FORMAT_STEREO_FLOAT32                 0x10011
+#endif
+
+#ifndef AL_EXT_double
+#define AL_EXT_double 1
+#define AL_FORMAT_MONO_DOUBLE_EXT                0x10012
+#define AL_FORMAT_STEREO_DOUBLE_EXT              0x10013
+#endif
+
+#ifndef ALC_LOKI_audio_channel
+#define ALC_LOKI_audio_channel 1
+#define ALC_CHAN_MAIN_LOKI                       0x500001
+#define ALC_CHAN_PCM_LOKI                        0x500002
+#define ALC_CHAN_CD_LOKI                         0x500003
+#endif
+
+#ifndef ALC_ENUMERATE_ALL_EXT
+#define ALC_ENUMERATE_ALL_EXT 1
+#define ALC_DEFAULT_ALL_DEVICES_SPECIFIER        0x1012
+#define ALC_ALL_DEVICES_SPECIFIER                0x1013
+#endif
+
+#ifndef AL_EXT_MCFORMATS
+#define AL_EXT_MCFORMATS 1
+#define AL_FORMAT_QUAD8                          0x1204
+#define AL_FORMAT_QUAD16                         0x1205
+#define AL_FORMAT_QUAD32                         0x1206
+#define AL_FORMAT_REAR8                          0x1207
+#define AL_FORMAT_REAR16                         0x1208
+#define AL_FORMAT_REAR32                         0x1209
+#define AL_FORMAT_51CHN8                         0x120A
+#define AL_FORMAT_51CHN16                        0x120B
+#define AL_FORMAT_51CHN32                        0x120C
+#define AL_FORMAT_61CHN8                         0x120D
+#define AL_FORMAT_61CHN16                        0x120E
+#define AL_FORMAT_61CHN32                        0x120F
+#define AL_FORMAT_71CHN8                         0x1210
+#define AL_FORMAT_71CHN16                        0x1211
+#define AL_FORMAT_71CHN32                        0x1212
+#endif
+
+#ifndef AL_EXT_MULAW_MCFORMATS
+#define AL_EXT_MULAW_MCFORMATS 1
+#define AL_FORMAT_MONO_MULAW                     0x10014
+#define AL_FORMAT_STEREO_MULAW                   0x10015
+#define AL_FORMAT_QUAD_MULAW                     0x10021
+#define AL_FORMAT_REAR_MULAW                     0x10022
+#define AL_FORMAT_51CHN_MULAW                    0x10023
+#define AL_FORMAT_61CHN_MULAW                    0x10024
+#define AL_FORMAT_71CHN_MULAW                    0x10025
+#endif
+
+#ifndef AL_EXT_IMA4
+#define AL_EXT_IMA4 1
+#define AL_FORMAT_MONO_IMA4                      0x1300
+#define AL_FORMAT_STEREO_IMA4                    0x1301
+#endif
+
+#ifndef ALC_EXT_thread_local_context
+#define ALC_EXT_thread_local_context 1
+typedef ALCboolean  (ALC_APIENTRY*PFNALCSETTHREADCONTEXTPROC)(ALCcontext *context);
+typedef ALCcontext* (ALC_APIENTRY*PFNALCGETTHREADCONTEXTPROC)(void);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/main.h b/include/main.h
new file mode 100644 (file)
index 0000000..2f6c17a
--- /dev/null
@@ -0,0 +1,355 @@
+#ifndef MAIN_H
+#define MAIN_H
+
+#include "AL/alure.h"
+#include "alext.h"
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#endif
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+
+#ifdef HAVE_WINDOWS_H
+
+#include <windows.h>
+
+#ifdef _MSC_VER
+ #if _MSC_VER >= 1600
+  #define typeof decltype
+ #endif
+#endif
+
+#else
+
+#ifdef HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <assert.h>
+#include <pthread.h>
+#ifdef HAVE_PTHREAD_NP_H
+#include <pthread_np.h>
+#endif
+#include <errno.h>
+
+typedef pthread_mutex_t CRITICAL_SECTION;
+void EnterCriticalSection(CRITICAL_SECTION *cs);
+void LeaveCriticalSection(CRITICAL_SECTION *cs);
+void InitializeCriticalSection(CRITICAL_SECTION *cs);
+void DeleteCriticalSection(CRITICAL_SECTION *cs);
+
+#endif
+
+#include <map>
+#include <streambuf>
+#include <istream>
+#include <list>
+#include <algorithm>
+#include <vector>
+#include <memory>
+
+static const union {
+    int val;
+    char b[sizeof(int)];
+} endian_test = { 1 };
+static const bool LittleEndian = (endian_test.b[0] != 0);
+static const bool BigEndian = !LittleEndian;
+
+
+#ifdef DYNLOAD
+void *OpenLib(const char *libname);
+void CloseLib(void *handle);
+void *GetLibProc(void *handle, const char *funcname);
+
+template<typename T>
+void LoadFunc(void *handle, const char *funcname, T **funcptr)
+{ *funcptr = reinterpret_cast<T*>(GetLibProc(handle, funcname)); }
+
+#define LOAD_FUNC(h, x) LoadFunc((h), #x, &(p##x));                          \
+if(!(p##x))                                                                  \
+{                                                                            \
+    CloseLib((h));                                                           \
+    (h) = NULL;                                                              \
+    return;                                                                  \
+}
+#endif
+
+
+extern PFNALCSETTHREADCONTEXTPROC palcSetThreadContext;
+extern PFNALCGETTHREADCONTEXTPROC palcGetThreadContext;
+#define alcSetThreadContext palcSetThreadContext
+#define alcGetThreadContext palcGetThreadContext
+
+void SetError(const char *err);
+ALuint DetectBlockAlignment(ALenum format);
+ALuint DetectCompressionRate(ALenum format);
+ALenum GetSampleFormat(ALuint channels, ALuint bits, bool isFloat);
+
+struct UserCallbacks {
+    void*     (*open_file)(const ALchar*);
+    void*     (*open_mem)(const ALubyte*,ALuint);
+    ALboolean (*get_fmt)(void*,ALenum*,ALuint*,ALuint*);
+    ALuint    (*decode)(void*,ALubyte*,ALuint);
+    ALboolean (*rewind)(void*);
+    void      (*close)(void*);
+};
+extern std::map<ALint,UserCallbacks> InstalledCallbacks;
+
+
+void StopStream(alureStream *stream);
+struct alureStream {
+    // Local copy of memory data
+    ALubyte *data;
+
+    // Storage when reading chunks
+    std::vector<ALubyte> dataChunk;
+
+    // Abstracted input stream
+    std::istream *fstream;
+
+    virtual bool IsValid() = 0;
+    virtual bool GetFormat(ALenum*,ALuint*,ALuint*) = 0;
+    virtual ALuint GetData(ALubyte*,ALuint) = 0;
+    virtual bool Rewind() = 0;
+    virtual bool SetOrder(ALuint order)
+    {
+        if(!order) return Rewind();
+        SetError("Invalid order for stream");
+        return false;
+    }
+    virtual bool SetPatchset(const char*)
+    { return true; }
+    virtual alureInt64 GetLength()
+    { return 0; }
+
+    alureStream(std::istream *_stream)
+      : data(NULL), fstream(_stream)
+    { StreamList.push_front(this); }
+    virtual ~alureStream()
+    {
+        delete[] data;
+        StreamList.erase(std::find(StreamList.begin(), StreamList.end(), this));
+    }
+
+    static void Clear(void)
+    {
+        while(StreamList.size() > 0)
+        {
+            alureStream *stream = *(StreamList.begin());
+            StopStream(stream);
+            std::istream *f = stream->fstream;
+            delete stream;
+            delete f;
+        }
+    }
+
+    static bool Verify(alureStream *stream)
+    {
+        ListType::iterator i = std::find(StreamList.begin(), StreamList.end(), stream);
+        return (i != StreamList.end());
+    }
+
+private:
+    typedef std::list<alureStream*> ListType;
+    static ListType StreamList;
+};
+
+
+struct MemDataInfo {
+    const ALubyte *Data;
+    size_t Length;
+    size_t Pos;
+
+    MemDataInfo() : Data(NULL), Length(0), Pos(0)
+    { }
+    MemDataInfo(const MemDataInfo &inf) : Data(inf.Data), Length(inf.Length),
+                                          Pos(inf.Pos)
+    { }
+};
+
+class MemStreamBuf : public std::streambuf {
+    MemDataInfo memInfo;
+
+    virtual int_type underflow();
+    virtual pos_type seekoff(off_type offset, std::ios_base::seekdir whence, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out);
+    virtual pos_type seekpos(pos_type pos, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out);
+
+public:
+    MemStreamBuf(const MemDataInfo &data)
+      : memInfo(data)
+    {
+        memInfo.Pos /= sizeof(char_type);
+        memInfo.Length /= sizeof(char_type);
+    }
+    virtual ~MemStreamBuf() { }
+};
+
+struct UserFuncs {
+    void* (*open)(const char *filename, ALuint mode);
+    void (*close)(void *f);
+    ALsizei (*read)(void *f, ALubyte *buf, ALuint count);
+    ALsizei (*write)(void *f, const ALubyte *buf, ALuint count);
+    alureInt64 (*seek)(void *f, alureInt64 offset, int whence);
+};
+extern UserFuncs Funcs;
+extern bool UsingSTDIO;
+
+class FileStreamBuf : public std::streambuf {
+    void *usrFile;
+    UserFuncs fio;
+
+    char buffer[1024];
+
+    virtual int_type underflow();
+    virtual pos_type seekoff(off_type offset, std::ios_base::seekdir whence, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out);
+    virtual pos_type seekpos(pos_type pos, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out);
+
+public:
+    bool IsOpen()
+    { return usrFile != NULL; }
+
+    FileStreamBuf(const char *filename, ALint mode)
+      : usrFile(NULL), fio(Funcs)
+    { usrFile = fio.open(filename, mode); }
+    virtual ~FileStreamBuf()
+    { if(usrFile) fio.close(usrFile); }
+};
+
+class InStream : public std::istream {
+public:
+    InStream(const char *filename)
+      : std::istream(new FileStreamBuf(filename, 0))
+    {
+        if(!(static_cast<FileStreamBuf*>(rdbuf())->IsOpen()))
+            clear(failbit);
+    }
+    InStream(const MemDataInfo &memInfo)
+      : std::istream(new MemStreamBuf(memInfo))
+    { }
+    virtual ~InStream()
+    { delete rdbuf(); }
+};
+
+
+static inline ALuint read_le32(std::istream *file)
+{
+    ALubyte buffer[4];
+    if(!file->read(reinterpret_cast<char*>(buffer), 4)) return 0;
+    return buffer[0] | (buffer[1]<<8) | (buffer[2]<<16) | (buffer[3]<<24);
+}
+
+static inline ALushort read_le16(std::istream *file)
+{
+    ALubyte buffer[2];
+    if(!file->read(reinterpret_cast<char*>(buffer), 2)) return 0;
+    return buffer[0] | (buffer[1]<<8);
+}
+
+static inline ALuint read_be32(std::istream *file)
+{
+    ALubyte buffer[4];
+    if(!file->read(reinterpret_cast<char*>(buffer), 4)) return 0;
+    return (buffer[0]<<24) | (buffer[1]<<16) | (buffer[2]<<8) | buffer[3];
+}
+
+static inline ALushort read_be16(std::istream *file)
+{
+    ALubyte buffer[2];
+    if(!file->read(reinterpret_cast<char*>(buffer), 2)) return 0;
+    return (buffer[0]<<8) | buffer[1];
+}
+
+static inline ALuint read_be80extended(std::istream *file)
+{
+    ALubyte buffer[10];
+    if(!file->read(reinterpret_cast<char*>(buffer), 10)) return 0;
+    ALuint mantissa, last = 0;
+    ALubyte exp = buffer[1];
+    exp = 30 - exp;
+    mantissa = (buffer[2]<<24) | (buffer[3]<<16) | (buffer[4]<<8) | buffer[5];
+    while (exp--)
+    {
+        last = mantissa;
+        mantissa >>= 1;
+    }
+    if((last&1)) mantissa++;
+    return mantissa;
+}
+
+
+extern CRITICAL_SECTION cs_StreamPlay;
+
+alureStream *create_stream(const char *fname);
+alureStream *create_stream(const MemDataInfo &memData);
+alureStream *create_stream(ALvoid *userdata, ALenum format, ALuint rate, const UserCallbacks &cb);
+
+template <typename T>
+const T& clamp(const T& val, const T& min, const T& max)
+{ return std::max(std::min(val, max), min); }
+
+template <typename T>
+void swap(T &val1, T &val2)
+{
+    val1 ^= val2;
+    val2 ^= val1;
+    val1 ^= val2;
+}
+
+
+template<typename T1, typename T2>
+T1 SearchSecond(T1 start, T1 end, T2 val)
+{
+    while(start != end && start->second != val)
+        ++start;
+    return start;
+}
+
+struct Decoder {
+    typedef std::auto_ptr<alureStream>(*FactoryType)(std::istream*);
+    typedef std::multimap<ALint,FactoryType> ListType;
+
+    static const ListType& GetList();
+
+protected:
+    static ListType& AddList(FactoryType func=NULL, ALint prio=0);
+};
+
+template<typename T, ALint prio>
+struct DecoderDecl : public Decoder {
+    DecoderDecl()
+    {
+        T::Init();
+        AddList(Factory, prio);
+    }
+    ~DecoderDecl()
+    {
+        ListType &list = AddList();
+        list.erase(SearchSecond(list.begin(), list.end(), Factory));
+        T::Deinit();
+    }
+
+private:
+    static std::auto_ptr<alureStream> Factory(std::istream *file)
+    {
+        std::auto_ptr<alureStream> ret(new T(file));
+        if(ret->IsValid()) return ret;
+        return std::auto_ptr<alureStream>();
+    }
+};
+
+Decoder &alure_init_wav(void);
+Decoder &alure_init_aiff(void);
+Decoder &alure_init_vorbisfile(void);
+Decoder &alure_init_flac(void);
+Decoder &alure_init_sndfile(void);
+Decoder &alure_init_fluidsynth(void);
+Decoder &alure_init_dumb(void);
+Decoder &alure_init_modplug(void);
+Decoder &alure_init_mpg123(void);
+
+#endif // MAIN_H
diff --git a/libalure.map b/libalure.map
new file mode 100644 (file)
index 0000000..306eaff
--- /dev/null
@@ -0,0 +1,45 @@
+LIBALURE_1.0 {
+  global:
+    alureGetVersion;
+    alureGetErrorString;
+    alureGetDeviceNames;
+    alureFreeDeviceNames;
+    alureInitDevice;
+    alureShutdownDevice;
+    alureGetSampleFormat;
+    alureSleep;
+    alureCreateBufferFromFile;
+    alureCreateBufferFromMemory;
+    alureBufferDataFromFile;
+    alureBufferDataFromMemory;
+    alureCreateStreamFromFile;
+    alureCreateStreamFromMemory;
+    alureCreateStreamFromStaticMemory;
+    alureCreateStreamFromCallback;
+    alureBufferDataFromStream;
+    alureRewindStream;
+    alureDestroyStream;
+    alureInstallDecodeCallbacks;
+
+  local: *;
+};
+LIBALURE_1.1 {
+  global:
+    alureGetStreamFrequency;
+    alureSetStreamOrder;
+    alureSetStreamPatchset;
+    alureStreamSizeIsMicroSec;
+    alureUpdate;
+    alureUpdateInterval;
+    alurePlaySourceStream;
+    alurePlaySource;
+    alureStopSource;
+    alurePauseSource;
+    alureResumeSource;
+    alureSetIOCallbacks;
+    alureGetProcAddress;
+} LIBALURE_1.0;
+LIBALURE_1.2 {
+  global:
+    alureGetStreamLength;
+} LIBALURE_1.1;
diff --git a/src/alure.cpp b/src/alure.cpp
new file mode 100644 (file)
index 0000000..35e7d7b
--- /dev/null
@@ -0,0 +1,800 @@
+/*
+ * ALURE  OpenAL utility library
+ * Copyright (c) 2009 by Chris Robinson.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+/* Title: Main and Miscellanious */
+
+#include "config.h"
+
+#include "main.h"
+
+#include <string.h>
+#include <errno.h>
+#include <stdio.h>
+#include <time.h>
+#ifdef HAVE_WINDOWS_H
+#include <windows.h>
+#endif
+
+#include <vector>
+#include <string>
+#include <map>
+
+std::map<ALint,UserCallbacks> InstalledCallbacks;
+CRITICAL_SECTION cs_StreamPlay;
+alureStream::ListType alureStream::StreamList;
+
+PFNALCSETTHREADCONTEXTPROC palcSetThreadContext;
+PFNALCGETTHREADCONTEXTPROC palcGetThreadContext;
+
+
+template<typename T>
+static inline void LoadALCProc(ALCdevice *dev, const char *name, T **ptr)
+{ *ptr = reinterpret_cast<T*>(alcGetProcAddress(dev, name)); }
+
+
+#ifdef HAVE_GCC_CONSTRUCTOR
+static void init_alure(void) __attribute__((constructor));
+static void deinit_alure(void) __attribute__((destructor));
+static struct MyConstructorClass {
+    ~MyConstructorClass()
+    { alureStream::Clear(); };
+} MyConstructor;
+#elif defined(_WIN32) && !defined(ALURE_STATIC_LIBRARY)
+static void init_alure(void);
+static void deinit_alure(void);
+static struct MyConstructorClass {
+    ~MyConstructorClass()
+    { alureStream::Clear(); };
+} MyConstructor;
+
+extern "C" BOOL APIENTRY DllMain(HINSTANCE module, DWORD reason, LPVOID /*reserved*/)
+{
+    // Perform actions based on the reason for calling.
+    switch(reason)
+    {
+        case DLL_PROCESS_ATTACH:
+            DisableThreadLibraryCalls(module);
+            init_alure();
+            break;
+
+        case DLL_PROCESS_DETACH:
+            deinit_alure();
+            break;
+    }
+    return TRUE;
+}
+#else
+static void init_alure(void);
+static void deinit_alure(void);
+
+static struct MyConstructorClass {
+    MyConstructorClass()
+    { init_alure(); };
+    ~MyConstructorClass()
+    { alureStream::Clear();
+      deinit_alure(); };
+} MyConstructor;
+#endif
+
+static void init_alure(void)
+{
+    InitializeCriticalSection(&cs_StreamPlay);
+
+    // These calls actually just return references to the codecs' Decoder
+    // objects. They aren't really used for anything other than to prevent the
+    // compiler from removing the codec initializers.
+    alure_init_wav();
+    alure_init_aiff();
+#ifdef HAS_VORBISFILE
+    alure_init_vorbisfile();
+#endif
+#ifdef HAS_FLAC
+    alure_init_flac();
+#endif
+#ifdef HAS_SNDFILE
+    alure_init_sndfile();
+#endif
+#ifdef HAS_FLUIDSYNTH
+    alure_init_fluidsynth();
+#endif
+#ifdef HAS_DUMB
+    alure_init_dumb();
+#endif
+#ifdef HAS_MODPLUG
+    alure_init_modplug();
+#endif
+#ifdef HAS_MPG123
+    alure_init_mpg123();
+#endif
+
+    if(alcIsExtensionPresent(NULL, "ALC_EXT_thread_local_context"))
+    {
+        LoadALCProc(NULL, "alcSetThreadContext", &palcSetThreadContext);
+        LoadALCProc(NULL, "alcGetThreadContext", &palcGetThreadContext);
+        if(!palcSetThreadContext || !palcGetThreadContext)
+        {
+            fprintf(stderr, "Alure lib: ALC_EXT_thread_local_context advertised, but missing function:\n"
+                            "    alcSetThreadContext=%p\n"
+                            "    alcGetThreadContext=%p\n",
+                            palcSetThreadContext, palcGetThreadContext);
+            palcSetThreadContext = NULL;
+            palcGetThreadContext = NULL;
+        }
+    }
+}
+
+static void deinit_alure(void)
+{
+    alureUpdateInterval(0.0f);
+    DeleteCriticalSection(&cs_StreamPlay);
+}
+
+
+#ifndef HAVE_WINDOWS_H
+
+void EnterCriticalSection(CRITICAL_SECTION *cs)
+{
+    int ret;
+    ret = pthread_mutex_lock(cs);
+    assert(ret == 0);
+}
+void LeaveCriticalSection(CRITICAL_SECTION *cs)
+{
+    int ret;
+    ret = pthread_mutex_unlock(cs);
+    assert(ret == 0);
+}
+void InitializeCriticalSection(CRITICAL_SECTION *cs)
+{
+    pthread_mutexattr_t attrib;
+    int ret;
+
+    ret = pthread_mutexattr_init(&attrib);
+    assert(ret == 0);
+
+    ret = pthread_mutexattr_settype(&attrib, PTHREAD_MUTEX_RECURSIVE);
+#ifdef HAVE_PTHREAD_NP_H
+    if(ret != 0)
+        ret = pthread_mutexattr_setkind_np(&attrib, PTHREAD_MUTEX_RECURSIVE);
+#endif
+    assert(ret == 0);
+    ret = pthread_mutex_init(cs, &attrib);
+    assert(ret == 0);
+
+    pthread_mutexattr_destroy(&attrib);
+}
+void DeleteCriticalSection(CRITICAL_SECTION *cs)
+{
+    int ret;
+    ret = pthread_mutex_destroy(cs);
+    assert(ret == 0);
+}
+
+#endif
+
+#ifdef DYNLOAD
+#ifdef _WIN32
+void *OpenLib(const char *libname)
+{ return LoadLibraryA(libname); }
+void CloseLib(void *hdl)
+{ FreeLibrary((HINSTANCE)hdl); }
+void *GetLibProc(void *hdl, const char *funcname)
+{ return (void*)GetProcAddress((HINSTANCE)hdl, funcname); }
+#else
+void *OpenLib(const char *libname)
+{
+    const char *err = dlerror();
+    void *hdl = dlopen(libname, RTLD_NOW);
+    if((err=dlerror()) != NULL)
+    {
+        fprintf(stderr, "Error loading %s: %s\n", libname, err);
+        return NULL;
+    }
+    return hdl;
+}
+void *GetLibProc(void *hdl, const char *funcname)
+{
+    const char *err = dlerror();
+    void *fn = dlsym(hdl, funcname);
+    if((err=dlerror()) != NULL)
+    {
+        fprintf(stderr, "Error loading %s: %s\n", funcname, err);
+        return NULL;
+    }
+    return fn;
+}
+void CloseLib(void *hdl)
+{ dlclose(hdl); }
+#endif
+#endif
+
+
+static const ALchar *last_error = "No error";
+void SetError(const char *err)
+{
+    last_error = err;
+}
+
+
+ALuint DetectBlockAlignment(ALenum format)
+{
+    switch(format)
+    {
+#define CHECK_RET(f,s) case (f): return (s)
+        CHECK_RET(AL_FORMAT_MONO8, sizeof(ALubyte));
+        CHECK_RET(AL_FORMAT_MONO16, sizeof(ALshort));
+        CHECK_RET(AL_FORMAT_MONO_FLOAT32, sizeof(ALfloat));
+        CHECK_RET(AL_FORMAT_MONO_DOUBLE_EXT, sizeof(ALdouble));
+        CHECK_RET(AL_FORMAT_MONO_MULAW, sizeof(ALubyte)*1);
+
+        CHECK_RET(AL_FORMAT_STEREO8, sizeof(ALubyte)*2);
+        CHECK_RET(AL_FORMAT_STEREO16, sizeof(ALshort)*2);
+        CHECK_RET(AL_FORMAT_STEREO_FLOAT32, sizeof(ALfloat)*2);
+        CHECK_RET(AL_FORMAT_STEREO_DOUBLE_EXT, sizeof(ALdouble)*2);
+        CHECK_RET(AL_FORMAT_STEREO_MULAW, sizeof(ALubyte)*2);
+
+        CHECK_RET(AL_FORMAT_QUAD8, sizeof(ALubyte)*4);
+        CHECK_RET(AL_FORMAT_QUAD16, sizeof(ALshort)*4);
+        CHECK_RET(AL_FORMAT_QUAD32, sizeof(ALfloat)*4);
+        CHECK_RET(AL_FORMAT_QUAD_MULAW, sizeof(ALubyte)*4);
+
+        CHECK_RET(AL_FORMAT_REAR8, sizeof(ALubyte)*2);
+        CHECK_RET(AL_FORMAT_REAR16, sizeof(ALshort)*2);
+        CHECK_RET(AL_FORMAT_REAR32, sizeof(ALfloat)*2);
+        CHECK_RET(AL_FORMAT_REAR_MULAW, sizeof(ALubyte)*2);
+
+        CHECK_RET(AL_FORMAT_51CHN8, sizeof(ALubyte)*6);
+        CHECK_RET(AL_FORMAT_51CHN16, sizeof(ALshort)*6);
+        CHECK_RET(AL_FORMAT_51CHN32, sizeof(ALfloat)*6);
+        CHECK_RET(AL_FORMAT_51CHN_MULAW, sizeof(ALubyte)*6);
+
+        CHECK_RET(AL_FORMAT_61CHN8, sizeof(ALubyte)*7);
+        CHECK_RET(AL_FORMAT_61CHN16, sizeof(ALshort)*7);
+        CHECK_RET(AL_FORMAT_61CHN32, sizeof(ALfloat)*7);
+        CHECK_RET(AL_FORMAT_61CHN_MULAW, sizeof(ALubyte)*7);
+
+        CHECK_RET(AL_FORMAT_71CHN8, sizeof(ALubyte)*8);
+        CHECK_RET(AL_FORMAT_71CHN16, sizeof(ALshort)*8);
+        CHECK_RET(AL_FORMAT_71CHN32, sizeof(ALfloat)*8);
+        CHECK_RET(AL_FORMAT_71CHN_MULAW, sizeof(ALubyte)*8);
+
+        CHECK_RET(AL_FORMAT_MONO_IMA4, 36);
+        CHECK_RET(AL_FORMAT_STEREO_IMA4, 36*2);
+#undef CHECK_RET
+    }
+    return 0;
+}
+
+ALuint DetectCompressionRate(ALenum format)
+{
+    switch(format)
+    {
+    case AL_FORMAT_MONO8:
+    case AL_FORMAT_MONO16:
+    case AL_FORMAT_MONO_FLOAT32:
+    case AL_FORMAT_MONO_DOUBLE_EXT:
+    case AL_FORMAT_STEREO8:
+    case AL_FORMAT_STEREO16:
+    case AL_FORMAT_STEREO_FLOAT32:
+    case AL_FORMAT_STEREO_DOUBLE_EXT:
+    case AL_FORMAT_QUAD8:
+    case AL_FORMAT_QUAD16:
+    case AL_FORMAT_QUAD32:
+    case AL_FORMAT_REAR8:
+    case AL_FORMAT_REAR16:
+    case AL_FORMAT_REAR32:
+    case AL_FORMAT_51CHN8:
+    case AL_FORMAT_51CHN16:
+    case AL_FORMAT_51CHN32:
+    case AL_FORMAT_61CHN8:
+    case AL_FORMAT_61CHN16:
+    case AL_FORMAT_61CHN32:
+    case AL_FORMAT_71CHN8:
+    case AL_FORMAT_71CHN16:
+    case AL_FORMAT_71CHN32:
+        return 1;
+
+    case AL_FORMAT_MONO_MULAW:
+    case AL_FORMAT_STEREO_MULAW:
+    case AL_FORMAT_QUAD_MULAW:
+    case AL_FORMAT_REAR_MULAW:
+    case AL_FORMAT_51CHN_MULAW:
+    case AL_FORMAT_61CHN_MULAW:
+    case AL_FORMAT_71CHN_MULAW:
+        return 1;
+
+    case AL_FORMAT_MONO_IMA4:
+    case AL_FORMAT_STEREO_IMA4:
+        return 65;
+    }
+    fprintf(stderr, "Alure lib: Unhandled format: %#x\n", format);
+    return 0;
+}
+
+ALenum GetSampleFormat(ALuint channels, ALuint bits, bool isFloat)
+{
+#define CHECK_FMT_RET(f) do {                                                 \
+    ALenum fmt = alGetEnumValue(#f);                                          \
+    if(alGetError() == AL_NO_ERROR && fmt != 0 && fmt != -1)                  \
+        return fmt;                                                           \
+} while(0)
+    if(!isFloat)
+    {
+        if(bits == 8)
+        {
+            if(channels == 1) CHECK_FMT_RET(AL_FORMAT_MONO8);
+            if(channels == 2) CHECK_FMT_RET(AL_FORMAT_STEREO8);
+            if(alIsExtensionPresent("AL_EXT_MCFORMATS"))
+            {
+                if(channels == 4) CHECK_FMT_RET(AL_FORMAT_QUAD8);
+                if(channels == 6) CHECK_FMT_RET(AL_FORMAT_51CHN8);
+                if(channels == 7) CHECK_FMT_RET(AL_FORMAT_61CHN8);
+                if(channels == 8) CHECK_FMT_RET(AL_FORMAT_71CHN8);
+            }
+            if(alIsExtensionPresent("AL_LOKI_quadriphonic"))
+            {
+                if(channels == 4) CHECK_FMT_RET(AL_FORMAT_QUAD8_LOKI);
+            }
+            SetError("Unsupported 8-bit channel count\n");
+            return AL_NONE;
+        }
+        if(bits == 16)
+        {
+            if(channels == 1) CHECK_FMT_RET(AL_FORMAT_MONO16);
+            if(channels == 2) CHECK_FMT_RET(AL_FORMAT_STEREO16);
+            if(alIsExtensionPresent("AL_EXT_MCFORMATS"))
+            {
+                if(channels == 4) CHECK_FMT_RET(AL_FORMAT_QUAD16);
+                if(channels == 6) CHECK_FMT_RET(AL_FORMAT_51CHN16);
+                if(channels == 7) CHECK_FMT_RET(AL_FORMAT_61CHN16);
+                if(channels == 8) CHECK_FMT_RET(AL_FORMAT_71CHN16);
+            }
+            if(alIsExtensionPresent("AL_LOKI_quadriphonic"))
+            {
+                if(channels == 4) CHECK_FMT_RET(AL_FORMAT_QUAD16_LOKI);
+            }
+            SetError("Unsupported 16-bit channel count\n");
+            return AL_NONE;
+        }
+        SetError("Unsupported PCM bit depth\n");
+        return AL_NONE;
+    }
+
+    if(bits == 32 && alIsExtensionPresent("AL_EXT_FLOAT32"))
+    {
+        if(channels == 1) CHECK_FMT_RET(AL_FORMAT_MONO_FLOAT32);
+        if(channels == 2) CHECK_FMT_RET(AL_FORMAT_STEREO_FLOAT32);
+        if(alIsExtensionPresent("AL_EXT_MCFORMATS"))
+        {
+            if(channels == 4) CHECK_FMT_RET(AL_FORMAT_QUAD32);
+            if(channels == 6) CHECK_FMT_RET(AL_FORMAT_51CHN32);
+            if(channels == 7) CHECK_FMT_RET(AL_FORMAT_61CHN32);
+            if(channels == 8) CHECK_FMT_RET(AL_FORMAT_71CHN32);
+        }
+        SetError("Unsupported float32 channel count\n");
+        return AL_NONE;
+    }
+    if(bits == 64 && alIsExtensionPresent("AL_EXT_DOUBLE"))
+    {
+        if(channels == 1) CHECK_FMT_RET(AL_FORMAT_MONO_DOUBLE_EXT);
+        if(channels == 2) CHECK_FMT_RET(AL_FORMAT_STEREO_DOUBLE_EXT);
+        SetError("Unsupported double channel count\n");
+        return AL_NONE;
+    }
+#undef CHECK_FMT_RET
+
+    SetError("Unsupported float bit depth\n");
+    return AL_NONE;
+}
+
+extern "C" {
+
+/* Function: alureGetVersion
+ *
+ * Stores the major and minor version of the library. If either major or minor
+ * are NULL, that value is not provided.
+ */
+ALURE_API void ALURE_APIENTRY alureGetVersion(ALuint *major, ALuint *minor)
+{
+    if(major) *major = ALURE_VER_MAJOR;
+    if(minor) *minor = ALURE_VER_MINOR;
+}
+
+/* Function: alureGetErrorString
+ *
+ * Returns a string describing the last error encountered.
+ */
+ALURE_API const ALchar* ALURE_APIENTRY alureGetErrorString(void)
+{
+    const ALchar *ret = last_error;
+    last_error = "No error";
+    return ret;
+}
+
+
+/* Function: alureGetDeviceNames
+ *
+ * Gets an array of device name strings from OpenAL. This encapsulates
+ * AL_ENUMERATE_ALL_EXT (if supported and 'all' is true) and standard
+ * enumeration, with 'count' being set to the number of returned device
+ * names.
+ *
+ * Returns:
+ * An array of device name strings, or NULL on error.
+ *
+ * See Also:
+ * <alureFreeDeviceNames>
+ */
+ALURE_API const ALCchar** ALURE_APIENTRY alureGetDeviceNames(ALCboolean all, ALCsizei *count)
+{
+    const ALCchar *list = NULL;
+    if(all && alcIsExtensionPresent(NULL, "ALC_ENUMERATE_ALL_EXT"))
+        list = alcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER);
+    else
+        list = alcGetString(NULL, ALC_DEVICE_SPECIFIER);
+    if(!list)
+    {
+        alcGetError(NULL);
+        SetError("No device names found");
+        return NULL;
+    }
+
+    const ALCchar *cur = list;
+    ALuint retlistLen = 0;
+    while(*cur)
+    {
+        cur += strlen(cur)+1;
+        retlistLen++;
+    }
+
+    const ALCchar **retlist = new const ALCchar*[retlistLen+1];
+    retlistLen = 0;
+    cur = list;
+    while(*cur)
+    {
+        ALCuint len = strlen(cur)+1;
+        ALCchar *newstr = new ALCchar[len];
+
+        memcpy(newstr, cur, len);
+        cur += len;
+
+        retlist[retlistLen] = newstr;
+        retlistLen++;
+    }
+    retlist[retlistLen] = NULL;
+
+    *count = retlistLen;
+    return retlist;
+}
+
+/* Function: alureFreeDeviceNames
+ *
+ * Frees the device name array returned from alureGetDeviceNames.
+ *
+ * See Also:
+ * <alureGetDeviceNames>
+ */
+ALURE_API ALvoid ALURE_APIENTRY alureFreeDeviceNames(const ALCchar **names)
+{
+    if(names)
+    {
+        for(ALCuint i = 0;names[i];i++)
+            delete[] const_cast<ALCchar*>(names[i]);
+        delete[] names;
+    }
+}
+
+
+/* Function: alureInitDevice
+ *
+ * Opens the named device, creates a context with the given attributes, and
+ * sets that context as current. The name and attribute list would be the same
+ * as what's passed to alcOpenDevice and alcCreateContext respectively.
+ *
+ * Returns:
+ * AL_FALSE on error.
+ *
+ * See Also:
+ * <alureShutdownDevice>
+ */
+ALURE_API ALboolean ALURE_APIENTRY alureInitDevice(const ALCchar *name, const ALCint *attribs)
+{
+    ALCdevice *device = alcOpenDevice(name);
+    if(!device)
+    {
+        alcGetError(NULL);
+
+        SetError("Device open failed");
+        return AL_FALSE;
+    }
+
+    ALCcontext *context = alcCreateContext(device, attribs);
+    if(!context || alcMakeContextCurrent(context) == ALC_FALSE)
+    {
+        if(context)
+            alcDestroyContext(context);
+        alcCloseDevice(device);
+
+        SetError("Context setup failed");
+        return AL_FALSE;
+    }
+    alcGetError(device);
+
+    return AL_TRUE;
+}
+
+/* Function: alureShutdownDevice
+ *
+ * Destroys the current context and closes its associated device.
+ *
+ * Returns:
+ * AL_FALSE on error.
+ *
+ * See Also:
+ * <alureInitDevice>
+ */
+ALURE_API ALboolean ALURE_APIENTRY alureShutdownDevice(void)
+{
+    ALCcontext *context = alcGetCurrentContext();
+    ALCdevice *device = alcGetContextsDevice(context);
+    if(!context || !device)
+    {
+        alcGetError(device);
+        SetError("Failed to get current device");
+        return AL_FALSE;
+    }
+
+    if(alcMakeContextCurrent(NULL) == ALC_FALSE)
+    {
+        alcGetError(NULL);
+        SetError("Failed to unset current context");
+        return AL_FALSE;
+    }
+
+    alcDestroyContext(context);
+    alcCloseDevice(device);
+    alcGetError(NULL);
+
+    return AL_TRUE;
+}
+
+
+/* Function: alureGetSampleFormat
+ *
+ * Retrieves an OpenAL format for the given sample format. If bits is non-0,
+ * floatbits must be 0, and if floatbits is non-0, bits must be 0. The
+ * application should not rely on any particular format enum being returned as
+ * it is dependant on the available extensions. The returned format will be
+ * valid for the current context. Requires an active context.
+ *
+ * Returns:
+ * An OpenAL format enum for the given sample format, or AL_NONE if one can't
+ * be found.
+ */
+ALURE_API ALenum ALURE_APIENTRY alureGetSampleFormat(ALuint channels, ALuint bits, ALuint floatbits)
+{
+    if(alGetError() != AL_NO_ERROR)
+    {
+        SetError("Existing OpenAL error");
+        return AL_NONE;
+    }
+
+    if(bits && floatbits)
+    {
+        SetError("Both bit-types specified");
+        return AL_NONE;
+    }
+
+    if(bits)
+        return GetSampleFormat(channels, bits, false);
+    return GetSampleFormat(channels, floatbits, true);
+}
+
+
+/* Function: alureInstallDecodeCallbacks
+ *
+ * Installs callbacks to enable ALURE to handle more file types. The index is
+ * the order that each given set of callbacks will be tried, starting at the
+ * most negative number (INT_MIN) and going up. Negative indices will be tried
+ * before the built-in decoders, and positive indices will be tried after.
+ * Installing callbacks onto the same index multiple times will remove the
+ * previous callbacks, and removing old callbacks won't affect any opened files
+ * using them (they'll continue to use the old functions until properly closed,
+ * although newly opened files will use the new ones). Passing NULL for all
+ * callbacks is a valid way to remove an installed set, otherwise certain
+ * callbacks must be specified. Callbacks that are not specified will assume
+ * failure.
+ *
+ * Parameters:
+ * open_file - This callback is expected to open the named file and prepare it
+ *             for decoding. If the callbacks cannot decode the file, NULL
+ *             should be returned to indicate failure. Upon success, a non-NULL
+ *             handle must be returned, which will be used as a unique
+ *             identifier for the decoder instance. This callback is required
+ *             if open_memory is not specified.
+ * open_memory - This callback behaves the same as open_file, except it takes a
+ *               memory segment for input instead of a filename. The given
+ *               memory will remain valid while the instance is open. This
+ *               callback is required if open_file is not specified.
+ * get_format - This callback is used to retrieve the format of the decoded
+ *              data for the given instance. It is the responsibility of the
+ *              function to make sure the returned format is valid for the
+ *              current AL context (eg. don't return AL_FORMAT_QUAD16 if the
+ *              AL_EXT_MCFORMATS extension isn't available). Returning 0 for
+ *              samplerate or blocksize, or returning AL_NONE for format, will
+ *              cause a failure. Returning AL_FALSE indicates failure. This
+ *              callback is required.
+ * decode - This callback is called to get more decoded data. Up to the
+ *          specified amount of bytes should be written to the data pointer.
+ *          The number of bytes written should be a multiple of the block size,
+ *          otherwise an OpenAL error may occur during buffering. The function
+ *          should return the number of bytes written. This callback is
+ *          required.
+ * rewind - This callback is for rewinding the instance so that the next decode
+ *          calls for it will get audio data from the start of the sound file.
+ *          If the stream fails to rewind, AL_FALSE should be returned.
+ * close - This callback is called at the end of processing for a particular
+ *         instance. The handle will not be used further and any associated
+ *         data may be deleted.
+ *
+ * Returns:
+ * AL_FALSE on error.
+ */
+ALURE_API ALboolean ALURE_APIENTRY alureInstallDecodeCallbacks(ALint index,
+      void*     (*open_file)(const ALchar *filename),
+      void*     (*open_memory)(const ALubyte *data, ALuint length),
+      ALboolean (*get_format)(void *instance, ALenum *format, ALuint *samplerate, ALuint *blocksize),
+      ALuint    (*decode)(void *instance, ALubyte *data, ALuint bytes),
+      ALboolean (*rewind)(void *instance),
+      void      (*close)(void *instance))
+{
+    if(!open_file && !open_memory && !get_format && !decode && !rewind && !close)
+    {
+        std::map<ALint,UserCallbacks>::iterator i = InstalledCallbacks.find(index);
+        if(i != InstalledCallbacks.end())
+            InstalledCallbacks.erase(i);
+        return AL_TRUE;
+    }
+
+    if((!open_file && !open_memory) || !get_format || !decode)
+    {
+        SetError("Missing callback functions");
+        return AL_FALSE;
+    }
+
+    UserCallbacks newcb;
+    newcb.open_file = open_file;
+    newcb.open_mem  = open_memory;
+    newcb.get_fmt   = get_format;
+    newcb.decode    = decode;
+    newcb.rewind    = rewind;
+    newcb.close     = close;
+
+    InstalledCallbacks[index] = newcb;
+
+    return AL_TRUE;
+}
+
+
+/* Function: alureSleep
+ *
+ * Rests the calling thread for the given number of seconds.
+ *
+ * Returns:
+ * AL_FALSE on error.
+ */
+ALURE_API ALboolean ALURE_APIENTRY alureSleep(ALfloat duration)
+{
+    if(duration < 0.0f)
+    {
+        SetError("Invalid duration");
+        return AL_FALSE;
+    }
+
+    ALuint seconds = (ALuint)duration;
+    ALdouble rest = duration - (ALdouble)seconds;
+
+#ifdef HAVE_NANOSLEEP
+
+    struct timespec t, remainingTime;
+    t.tv_sec = (time_t)seconds;
+    t.tv_nsec = (long)(rest*1000000000);
+
+    while(nanosleep(&t, &remainingTime) < 0 && errno == EINTR)
+        t = remainingTime;
+
+#elif defined(HAVE_WINDOWS_H)
+
+    while(seconds > 0)
+    {
+        Sleep(1000);
+        seconds--;
+    }
+    Sleep((DWORD)(rest * 1000));
+
+#endif
+
+    return AL_TRUE;
+}
+
+
+/* Function: alureGetProcAddress
+ *
+ * Returns a pointer for the named ALURE function.
+ *
+ * Returns:
+ * NULL on error.
+ *
+ * *Version Added*: 1.1
+ */
+ALURE_API void* ALURE_APIENTRY alureGetProcAddress(const ALchar *funcname)
+{
+    static const struct {
+        const char *name;
+        void *func;
+    } FunctionList[] = {
+#define ADD_FUNCTION(x) { #x, (void*)x },
+        ADD_FUNCTION(alureGetVersion)
+        ADD_FUNCTION(alureGetErrorString)
+        ADD_FUNCTION(alureGetDeviceNames)
+        ADD_FUNCTION(alureFreeDeviceNames)
+        ADD_FUNCTION(alureInitDevice)
+        ADD_FUNCTION(alureShutdownDevice)
+        ADD_FUNCTION(alureGetSampleFormat)
+        ADD_FUNCTION(alureSleep)
+        ADD_FUNCTION(alureCreateBufferFromFile)
+        ADD_FUNCTION(alureCreateBufferFromMemory)
+        ADD_FUNCTION(alureBufferDataFromFile)
+        ADD_FUNCTION(alureBufferDataFromMemory)
+        ADD_FUNCTION(alureCreateStreamFromFile)
+        ADD_FUNCTION(alureCreateStreamFromMemory)
+        ADD_FUNCTION(alureCreateStreamFromStaticMemory)
+        ADD_FUNCTION(alureCreateStreamFromCallback)
+        ADD_FUNCTION(alureGetStreamLength)
+        ADD_FUNCTION(alureRewindStream)
+        ADD_FUNCTION(alureDestroyStream)
+        ADD_FUNCTION(alureSetStreamOrder)
+        ADD_FUNCTION(alureSetStreamPatchset)
+        ADD_FUNCTION(alureInstallDecodeCallbacks)
+        ADD_FUNCTION(alureSetIOCallbacks)
+        ADD_FUNCTION(alureGetProcAddress)
+        ADD_FUNCTION(alurePlaySourceStream)
+        ADD_FUNCTION(alurePlaySource)
+        ADD_FUNCTION(alureStopSource)
+#undef ADD_FUNCTION
+        { NULL, NULL }
+    };
+
+    size_t i;
+    for(i = 0;FunctionList[i].name;i++)
+    {
+        if(strcmp(FunctionList[i].name, funcname) == 0)
+            break;
+    }
+
+    if(!FunctionList[i].name)
+        SetError("Function not found");
+    return FunctionList[i].func;
+}
+
+} // extern "C"
diff --git a/src/buffer.cpp b/src/buffer.cpp
new file mode 100644 (file)
index 0000000..f08be5c
--- /dev/null
@@ -0,0 +1,238 @@
+/*
+ * ALURE  OpenAL utility library
+ * Copyright (c) 2009 by Chris Robinson.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+/* Title: File Loading */
+
+#include "config.h"
+
+#include "main.h"
+
+#include <string.h>
+
+#include <vector>
+#include <memory>
+
+
+static bool load_stream(alureStream *_stream, ALuint buffer)
+{
+    if(!_stream)
+        return false;
+
+    std::auto_ptr<std::istream> fstream(_stream->fstream);
+    std::auto_ptr<alureStream> stream(_stream);
+
+    ALenum format;
+    ALuint freq, blockAlign;
+
+    if(!stream->GetFormat(&format, &freq, &blockAlign))
+    {
+        SetError("Could not get sample format");
+        return false;
+    }
+
+    if(format == AL_NONE)
+    {
+        SetError("No valid format");
+        return false;
+    }
+    if(blockAlign == 0)
+    {
+        SetError("Invalid block size");
+        return false;
+    }
+    if(freq == 0)
+    {
+        SetError("Invalid sample rate");
+        return false;
+    }
+
+    ALuint writePos = 0, got;
+    std::vector<ALubyte> data(freq*blockAlign);
+    while((got=stream->GetData(&data[writePos], data.size()-writePos)) > 0)
+    {
+        writePos += got;
+        data.resize(writePos + freq*blockAlign);
+    }
+    data.resize(writePos - (writePos%blockAlign));
+    stream.reset(NULL);
+
+    alBufferData(buffer, format, &data[0], data.size(), freq);
+    if(alGetError() != AL_NO_ERROR)
+    {
+        SetError("Buffer load failed");
+        return false;
+    }
+
+    return true;
+}
+
+extern "C" {
+
+/* Function: alureCreateBufferFromFile
+ *
+ * Loads the given file into a new OpenAL buffer object. The formats supported
+ * depend on the options the library was compiled with, what libraries are
+ * available at runtime, and the installed decode callbacks. Requires an active
+ * context.
+ *
+ * Returns:
+ * A new buffer ID with the loaded sound, or AL_NONE on error.
+ *
+ * See Also:
+ * <alureBufferDataFromFile>
+ */
+ALURE_API ALuint ALURE_APIENTRY alureCreateBufferFromFile(const ALchar *fname)
+{
+    if(alGetError() != AL_NO_ERROR)
+    {
+        SetError("Existing OpenAL error");
+        return AL_NONE;
+    }
+
+    ALuint buf;
+    alGenBuffers(1, &buf);
+    if(alGetError() != AL_NO_ERROR)
+    {
+        SetError("Buffer creation failed");
+        return AL_NONE;
+    }
+
+    if(alureBufferDataFromFile(fname, buf) == AL_FALSE)
+    {
+        alDeleteBuffers(1, &buf);
+        alGetError();
+        buf = AL_NONE;
+    }
+
+    return buf;
+}
+
+/* Function: alureCreateBufferFromMemory
+ *
+ * Loads a file image from memory into a new OpenAL buffer object, similar to
+ * alureCreateBufferFromFile. Requires an active context.
+ *
+ * Returns:
+ * A new buffer ID with the loaded sound, or AL_NONE on error.
+ *
+ * See Also:
+ * <alureBufferDataFromMemory>
+ */
+ALURE_API ALuint ALURE_APIENTRY alureCreateBufferFromMemory(const ALubyte *fdata, ALsizei length)
+{
+    if(alGetError() != AL_NO_ERROR)
+    {
+        SetError("Existing OpenAL error");
+        return AL_NONE;
+    }
+
+    ALuint buf;
+    alGenBuffers(1, &buf);
+    if(alGetError() != AL_NO_ERROR)
+    {
+        SetError("Buffer creation failed");
+        return AL_NONE;
+    }
+
+    if(alureBufferDataFromMemory(fdata, length, buf) == AL_FALSE)
+    {
+        alDeleteBuffers(1, &buf);
+        alGetError();
+        buf = AL_NONE;
+    }
+
+    return buf;
+}
+
+/* Function: alureBufferDataFromFile
+ *
+ * Loads the given file into an existing OpenAL buffer object. The previous
+ * contents of the buffer are replaced. Requires an active context.
+ *
+ * Returns:
+ * AL_FALSE on error.
+ *
+ * See Also:
+ * <alureCreateBufferFromFile>
+ */
+ALURE_API ALboolean ALURE_APIENTRY alureBufferDataFromFile(const ALchar *fname, ALuint buffer)
+{
+    if(alGetError() != AL_NO_ERROR)
+    {
+        SetError("Existing OpenAL error");
+        return AL_FALSE;
+    }
+
+    if(!buffer || !alIsBuffer(buffer))
+    {
+        SetError("Invalid buffer ID");
+        return false;
+    }
+
+    if(load_stream(create_stream(fname), buffer) == false)
+        return AL_FALSE;
+    return AL_TRUE;
+}
+
+/* Function: alureBufferDataFromMemory
+ *
+ * Loads a file image from memory into an existing OpenAL buffer object,
+ * similar to alureBufferDataFromFile. Requires an active context.
+ *
+ * Returns:
+ * AL_FALSE on error.
+ *
+ * See Also:
+ * <alureCreateBufferFromMemory>
+ */
+ALURE_API ALboolean ALURE_APIENTRY alureBufferDataFromMemory(const ALubyte *fdata, ALsizei length, ALuint buffer)
+{
+    if(alGetError() != AL_NO_ERROR)
+    {
+        SetError("Existing OpenAL error");
+        return AL_FALSE;
+    }
+
+    if(!buffer || !alIsBuffer(buffer))
+    {
+        SetError("Invalid buffer ID");
+        return false;
+    }
+
+    if(length < 0)
+    {
+        SetError("Invalid data length");
+        return AL_FALSE;
+    }
+
+    MemDataInfo memData;
+    memData.Data = fdata;
+    memData.Length = length;
+    memData.Pos = 0;
+
+    if(load_stream(create_stream(memData), buffer) == false)
+        return AL_FALSE;
+    return AL_TRUE;
+}
+
+} // extern "C"
diff --git a/src/codec_aiff.cpp b/src/codec_aiff.cpp
new file mode 100644 (file)
index 0000000..bcdca94
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+ * ALURE  OpenAL utility library
+ * Copyright (c) 2009-2010 by Chris Robinson.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "config.h"
+
+#include "main.h"
+
+#include <string.h>
+#include <assert.h>
+
+#include <istream>
+
+
+struct aiffStream : public alureStream {
+private:
+    ALenum format;
+    int samplerate;
+    int blockAlign;
+    int sampleSize;
+    int channels;
+    long dataStart;
+    long dataLen;
+    size_t remLen;
+
+public:
+    static void Init() { }
+    static void Deinit() { }
+
+    virtual bool IsValid()
+    { return (dataStart > 0 && format != AL_NONE); }
+
+    virtual bool GetFormat(ALenum *fmt, ALuint *frequency, ALuint *blockalign)
+    {
+        *fmt = format;
+        *frequency = samplerate;
+        *blockalign = blockAlign;
+        return true;
+    }
+
+    virtual ALuint GetData(ALubyte *data, ALuint bytes)
+    {
+        std::streamsize rem = ((remLen >= bytes) ? bytes : remLen) / blockAlign;
+        fstream->read(reinterpret_cast<char*>(data), rem*blockAlign);
+
+        std::streamsize got = fstream->gcount();
+        got -= got%blockAlign;
+        remLen -= got;
+
+        if(LittleEndian)
+        {
+            if(sampleSize == 2)
+            {
+                for(std::streamsize i = 0;i < got;i+=2)
+                    swap(data[i], data[i+1]);
+            }
+            else if(sampleSize == 4)
+            {
+                for(std::streamsize i = 0;i < got;i+=4)
+                {
+                    swap(data[i+0], data[i+3]);
+                    swap(data[i+1], data[i+2]);
+                }
+            }
+        }
+
+        return got;
+    }
+
+    virtual bool Rewind()
+    {
+        fstream->clear();
+        if(fstream->seekg(dataStart))
+        {
+            remLen = dataLen;
+            return true;
+        }
+
+        SetError("Seek failed");
+        return false;
+    }
+
+    virtual alureInt64 GetLength()
+    {
+        alureInt64 ret = dataLen;
+        return ret / channels * 8 / sampleSize;
+    }
+
+    aiffStream(std::istream *_fstream)
+      : alureStream(_fstream), format(0), dataStart(0)
+    {
+        ALubyte buffer[25];
+        int length;
+
+        if(!fstream->read(reinterpret_cast<char*>(buffer), 12) ||
+           memcmp(buffer, "FORM", 4) != 0 || memcmp(buffer+8, "AIFF", 4) != 0)
+            return;
+
+        while(!dataStart || format == AL_NONE)
+        {
+            char tag[4];
+            if(!fstream->read(tag, 4))
+                break;
+
+            /* read chunk length */
+            length = read_be32(fstream);
+
+            if(memcmp(tag, "COMM", 4) == 0 && length >= 18)
+            {
+                /* mono or stereo data */
+                channels = read_be16(fstream);
+
+                /* number of sample frames */
+                fstream->ignore(4);
+
+                /* bits per sample */
+                sampleSize = read_be16(fstream) / 8;
+
+                /* sample frequency */
+                samplerate = read_be80extended(fstream);
+
+                /* block alignment */
+                blockAlign = channels * sampleSize;
+
+                format = GetSampleFormat(channels, sampleSize*8, false);
+
+                length -= 18;
+            }
+            else if(memcmp(tag, "SSND", 4) == 0)
+            {
+                dataStart = fstream->tellg();
+                dataStart += 8;
+                dataLen = remLen = length - 8;
+            }
+
+            fstream->seekg(length, std::ios_base::cur);
+        }
+
+        if(dataStart > 0 && format != AL_NONE)
+            fstream->seekg(dataStart);
+    }
+
+    virtual ~aiffStream()
+    { }
+};
+// Priority = 9, prefer this decoder over external ones (but not the wave decoder)
+static DecoderDecl<aiffStream,9> aiffStream_decoder;
+Decoder &alure_init_aiff(void)
+{ return aiffStream_decoder; }
diff --git a/src/codec_dumb.cpp b/src/codec_dumb.cpp
new file mode 100644 (file)
index 0000000..8d24a7a
--- /dev/null
@@ -0,0 +1,316 @@
+/*
+ * ALURE  OpenAL utility library
+ * Copyright (c) 2009-2010 by Chris Robinson.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "config.h"
+
+#include "main.h"
+
+#include <string.h>
+#include <assert.h>
+
+#include <istream>
+
+#include <dumb.h>
+
+
+#ifdef DYNLOAD
+static void *dumb_handle;
+#define MAKE_FUNC(x) static typeof(x)* p##x
+MAKE_FUNC(dumbfile_open_ex);
+MAKE_FUNC(dumbfile_close);
+MAKE_FUNC(dumb_read_mod);
+MAKE_FUNC(dumb_read_s3m);
+MAKE_FUNC(dumb_read_xm);
+MAKE_FUNC(dumb_read_it);
+MAKE_FUNC(dumb_silence);
+MAKE_FUNC(duh_sigrenderer_generate_samples);
+MAKE_FUNC(duh_get_it_sigrenderer);
+MAKE_FUNC(duh_end_sigrenderer);
+MAKE_FUNC(unload_duh);
+MAKE_FUNC(dumb_it_start_at_order);
+MAKE_FUNC(dumb_it_set_loop_callback);
+MAKE_FUNC(dumb_it_sr_get_speed);
+MAKE_FUNC(dumb_it_sr_set_speed);
+#undef MAKE_FUNC
+
+#define dumbfile_open_ex pdumbfile_open_ex
+#define dumbfile_close pdumbfile_close
+#define dumb_read_mod pdumb_read_mod
+#define dumb_read_s3m pdumb_read_s3m
+#define dumb_read_xm pdumb_read_xm
+#define dumb_read_it pdumb_read_it
+#define dumb_silence pdumb_silence
+#define duh_sigrenderer_generate_samples pduh_sigrenderer_generate_samples
+#define duh_get_it_sigrenderer pduh_get_it_sigrenderer
+#define duh_end_sigrenderer pduh_end_sigrenderer
+#define unload_duh punload_duh
+#define dumb_it_start_at_order pdumb_it_start_at_order
+#define dumb_it_set_loop_callback pdumb_it_set_loop_callback
+#define dumb_it_sr_get_speed pdumb_it_sr_get_speed
+#define dumb_it_sr_set_speed pdumb_it_sr_set_speed
+#else
+#define dumb_handle 1
+#endif
+
+
+struct dumbStream : public alureStream {
+private:
+    DUMBFILE_SYSTEM vfs;
+    DUMBFILE *dumbFile;
+    DUH *duh;
+    DUH_SIGRENDERER *renderer;
+    std::vector<sample_t> sampleBuf;
+    ALuint lastOrder;
+    ALenum format;
+    ALCint samplerate;
+
+public:
+#ifdef DYNLOAD
+    static void Init()
+    {
+#ifdef _WIN32
+#define DUMB_LIB "libdumb.dll"
+#elif defined(__APPLE__)
+#define DUMB_LIB "libdumb.dylib"
+#else
+#define DUMB_LIB "libdumb.so"
+#endif
+
+        dumb_handle = OpenLib(DUMB_LIB);
+        if(!dumb_handle) return;
+
+        LOAD_FUNC(dumb_handle, dumbfile_open_ex);
+        LOAD_FUNC(dumb_handle, dumbfile_close);
+        LOAD_FUNC(dumb_handle, dumb_read_mod);
+        LOAD_FUNC(dumb_handle, dumb_read_s3m);
+        LOAD_FUNC(dumb_handle, dumb_read_xm);
+        LOAD_FUNC(dumb_handle, dumb_read_it);
+        LOAD_FUNC(dumb_handle, dumb_silence);
+        LOAD_FUNC(dumb_handle, duh_sigrenderer_generate_samples);
+        LOAD_FUNC(dumb_handle, duh_get_it_sigrenderer);
+        LOAD_FUNC(dumb_handle, duh_end_sigrenderer);
+        LOAD_FUNC(dumb_handle, unload_duh);
+        LOAD_FUNC(dumb_handle, dumb_it_start_at_order);
+        LOAD_FUNC(dumb_handle, dumb_it_set_loop_callback);
+        LOAD_FUNC(dumb_handle, dumb_it_sr_get_speed);
+        LOAD_FUNC(dumb_handle, dumb_it_sr_set_speed);
+    }
+    static void Deinit()
+    {
+        if(dumb_handle)
+            CloseLib(dumb_handle);
+        dumb_handle = NULL;
+    }
+#else
+    static void Init() { }
+    static void Deinit() { }
+#endif
+
+    virtual bool IsValid()
+    { return renderer != NULL; }
+
+    virtual bool GetFormat(ALenum *fmt, ALuint *frequency, ALuint *blockalign)
+    {
+        if(format == AL_NONE)
+        {
+            format = GetSampleFormat(2, 32, true);
+            if(format == AL_NONE)
+                format = AL_FORMAT_STEREO16;
+        }
+        *fmt = format;
+        *frequency = samplerate;
+        *blockalign = 2 * ((format==AL_FORMAT_STEREO16) ? sizeof(ALshort) :
+                                                          sizeof(ALfloat));
+        return true;
+    }
+
+    virtual ALuint GetData(ALubyte *data, ALuint bytes)
+    {
+        ALuint ret = 0;
+
+        if(dumb_it_sr_get_speed(duh_get_it_sigrenderer(renderer)) == 0)
+            return 0;
+
+        ALuint sample_count = bytes / ((format==AL_FORMAT_STEREO16) ?
+                                       sizeof(ALshort) : sizeof(ALfloat));
+
+        sampleBuf.resize(sample_count);
+        sample_t *samples[] = {
+            &sampleBuf[0]
+        };
+
+        dumb_silence(samples[0], sample_count);
+        ret = duh_sigrenderer_generate_samples(renderer, 1.0f, 65536.0f/samplerate, sample_count/2, samples);
+        ret *= 2;
+        if(format == AL_FORMAT_STEREO16)
+        {
+            for(ALuint i = 0;i < ret;i++)
+                ((ALshort*)data)[i] = clamp(samples[0][i]>>8, -32768, 32767);
+        }
+        else
+        {
+            for(ALuint i = 0;i < ret;i++)
+                ((ALfloat*)data)[i] = samples[0][i] * (1.0/8388607.0);
+        }
+        ret *= ((format==AL_FORMAT_STEREO16) ? sizeof(ALshort) : sizeof(ALfloat));
+
+        return ret;
+    }
+
+    virtual bool Rewind()
+    {
+        DUH_SIGRENDERER *newrenderer = dumb_it_start_at_order(duh, 2, lastOrder);
+        if(!newrenderer)
+        {
+            SetError("Could not start renderer");
+            return false;
+        }
+        duh_end_sigrenderer(renderer);
+        renderer = newrenderer;
+        return true;
+    }
+
+    virtual bool SetOrder(ALuint order)
+    {
+        DUH_SIGRENDERER *newrenderer = dumb_it_start_at_order(duh, 2, order);
+        if(!newrenderer)
+        {
+            SetError("Could not set order");
+            return false;
+        }
+        duh_end_sigrenderer(renderer);
+        renderer = newrenderer;
+
+        lastOrder = order;
+        return true;
+    }
+
+    dumbStream(std::istream *_fstream)
+      : alureStream(_fstream), dumbFile(NULL), duh(NULL), renderer(NULL),
+        lastOrder(0), format(AL_NONE), samplerate(48000)
+    {
+        if(!dumb_handle) return;
+
+        ALCdevice *device = alcGetContextsDevice(alcGetCurrentContext());
+        if(device) alcGetIntegerv(device, ALC_FREQUENCY, 1, &samplerate);
+
+        DUH* (*funcs[])(DUMBFILE*) = {
+            dumb_read_it,
+            dumb_read_xm,
+            dumb_read_s3m,
+            //dumb_read_mod,
+            NULL
+        };
+
+        vfs.open = NULL;
+        vfs.skip = skip;
+        vfs.getc = read_char;
+        vfs.getnc = read;
+        vfs.close = NULL;
+
+        for(size_t i = 0;funcs[i];i++)
+        {
+            dumbFile = dumbfile_open_ex(this, &vfs);
+            if(dumbFile)
+            {
+                duh = funcs[i](dumbFile);
+                if(duh)
+                {
+                    renderer = dumb_it_start_at_order(duh, 2, lastOrder);
+                    if(renderer)
+                    {
+                        dumb_it_set_loop_callback(duh_get_it_sigrenderer(renderer), loop_cb, this);
+                        break;
+                    }
+
+                    unload_duh(duh);
+                    duh = NULL;
+                }
+
+                dumbfile_close(dumbFile);
+                dumbFile = NULL;
+            }
+            fstream->clear();
+            fstream->seekg(0);
+        }
+    }
+
+    virtual ~dumbStream()
+    {
+        if(renderer)
+            duh_end_sigrenderer(renderer);
+        renderer = NULL;
+
+        if(duh)
+            unload_duh(duh);
+        duh = NULL;
+
+        if(dumbFile)
+            dumbfile_close(dumbFile);
+        dumbFile = NULL;
+    }
+
+private:
+    // DUMBFILE iostream callbacks
+    static int skip(void *user_data, long offset)
+    {
+        std::istream *stream = static_cast<dumbStream*>(user_data)->fstream;
+        stream->clear();
+
+        if(stream->seekg(offset, std::ios_base::cur))
+            return 0;
+        return -1;
+    }
+
+    static long read(char *ptr, long size, void *user_data)
+    {
+        std::istream *stream = static_cast<dumbStream*>(user_data)->fstream;
+        stream->clear();
+
+        stream->read(ptr, size);
+        return stream->gcount();
+    }
+
+    static int read_char(void *user_data)
+    {
+        std::istream *stream = static_cast<dumbStream*>(user_data)->fstream;
+        stream->clear();
+
+        unsigned char ret;
+        stream->read(reinterpret_cast<char*>(&ret), 1);
+        if(stream->gcount() > 0)
+            return ret;
+        return -1;
+    }
+
+    static int loop_cb(void *user_data)
+    {
+        dumbStream *self = static_cast<dumbStream*>(user_data);
+        dumb_it_sr_set_speed(duh_get_it_sigrenderer(self->renderer), 0);
+        return 0;
+    }
+};
+// Priority = -1, because mod loading can find false-positives
+static DecoderDecl<dumbStream,-1> dumbStream_decoder;
+Decoder &alure_init_dumb(void)
+{ return dumbStream_decoder; }
diff --git a/src/codec_flac.cpp b/src/codec_flac.cpp
new file mode 100644 (file)
index 0000000..5e6b0bd
--- /dev/null
@@ -0,0 +1,395 @@
+/*
+ * ALURE  OpenAL utility library
+ * Copyright (c) 2009-2010 by Chris Robinson.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "config.h"
+
+#include "main.h"
+
+#include <string.h>
+#include <assert.h>
+
+#include <istream>
+
+#include <FLAC/all.h>
+
+
+#ifdef DYNLOAD
+static void *flac_handle;
+#define MAKE_FUNC(x) static typeof(x)* p##x
+MAKE_FUNC(FLAC__stream_decoder_get_state);
+MAKE_FUNC(FLAC__stream_decoder_finish);
+MAKE_FUNC(FLAC__stream_decoder_new);
+MAKE_FUNC(FLAC__stream_decoder_seek_absolute);
+MAKE_FUNC(FLAC__stream_decoder_delete);
+MAKE_FUNC(FLAC__stream_decoder_get_total_samples);
+MAKE_FUNC(FLAC__stream_decoder_process_single);
+MAKE_FUNC(FLAC__stream_decoder_init_stream);
+#undef MAKE_FUNC
+
+#define FLAC__stream_decoder_get_state pFLAC__stream_decoder_get_state
+#define FLAC__stream_decoder_finish pFLAC__stream_decoder_finish
+#define FLAC__stream_decoder_new pFLAC__stream_decoder_new
+#define FLAC__stream_decoder_seek_absolute pFLAC__stream_decoder_seek_absolute
+#define FLAC__stream_decoder_delete pFLAC__stream_decoder_delete
+#define FLAC__stream_decoder_get_total_samples pFLAC__stream_decoder_get_total_samples
+#define FLAC__stream_decoder_process_single pFLAC__stream_decoder_process_single
+#define FLAC__stream_decoder_init_stream pFLAC__stream_decoder_init_stream
+#else
+#define flac_handle 1
+#endif
+
+
+struct flacStream : public alureStream {
+private:
+    FLAC__StreamDecoder *flacFile;
+    ALenum format;
+    ALuint samplerate;
+    ALuint blockAlign;
+    ALboolean useFloat;
+
+    std::vector<ALubyte> initialData;
+
+    ALubyte *outBytes;
+    ALuint outMax;
+    ALuint outLen;
+
+public:
+#ifdef DYNLOAD
+    static void Init()
+    {
+#ifdef _WIN32
+#define FLAC_LIB "libFLAC.dll"
+#elif defined(__APPLE__)
+#define FLAC_LIB "libFLAC.8.dylib"
+#else
+#define FLAC_LIB "libFLAC.so.8"
+#endif
+
+        flac_handle = OpenLib(FLAC_LIB);
+        if(!flac_handle) return;
+
+        LOAD_FUNC(flac_handle, FLAC__stream_decoder_get_state);
+        LOAD_FUNC(flac_handle, FLAC__stream_decoder_finish);
+        LOAD_FUNC(flac_handle, FLAC__stream_decoder_new);
+        LOAD_FUNC(flac_handle, FLAC__stream_decoder_seek_absolute);
+        LOAD_FUNC(flac_handle, FLAC__stream_decoder_delete);
+        LOAD_FUNC(flac_handle, FLAC__stream_decoder_get_total_samples);
+        LOAD_FUNC(flac_handle, FLAC__stream_decoder_process_single);
+        LOAD_FUNC(flac_handle, FLAC__stream_decoder_init_stream);
+    }
+    static void Deinit()
+    {
+        if(flac_handle)
+            CloseLib(flac_handle);
+        flac_handle = NULL;
+    }
+#else
+    static void Init() { }
+    static void Deinit() { }
+#endif
+
+    virtual bool IsValid()
+    { return flacFile != NULL; }
+
+    virtual bool GetFormat(ALenum *fmt, ALuint *frequency, ALuint *blockalign)
+    {
+        *fmt = format;
+        *frequency = samplerate;
+        *blockalign = blockAlign;
+        return true;
+    }
+
+    virtual ALuint GetData(ALubyte *data, ALuint bytes)
+    {
+        outBytes = data;
+        outLen = 0;
+        outMax = bytes;
+
+        if(initialData.size() > 0)
+        {
+            size_t rem = std::min(initialData.size(), (size_t)bytes);
+            memcpy(data, &initialData[0], rem);
+            outLen += rem;
+            initialData.erase(initialData.begin(), initialData.begin()+rem);
+        }
+
+        while(outLen < outMax)
+        {
+            if(FLAC__stream_decoder_process_single(flacFile) == false ||
+               FLAC__stream_decoder_get_state(flacFile) == FLAC__STREAM_DECODER_END_OF_STREAM)
+                break;
+        }
+
+        return outLen;
+    }
+
+    virtual bool Rewind()
+    {
+        if(FLAC__stream_decoder_seek_absolute(flacFile, 0) != false)
+        {
+            initialData.clear();
+            return true;
+        }
+
+        SetError("Seek failed");
+        return false;
+    }
+
+    virtual alureInt64 GetLength()
+    {
+        return FLAC__stream_decoder_get_total_samples(flacFile);
+    }
+
+    flacStream(std::istream *_fstream)
+      : alureStream(_fstream), flacFile(NULL), format(AL_NONE), samplerate(0),
+        blockAlign(0), useFloat(AL_FALSE)
+    {
+        if(!flac_handle) return;
+
+        flacFile = FLAC__stream_decoder_new();
+        if(flacFile)
+        {
+            if(FLAC__stream_decoder_init_stream(flacFile, ReadCallback, SeekCallback, TellCallback, LengthCallback, EofCallback, WriteCallback, MetadataCallback, ErrorCallback, this) == FLAC__STREAM_DECODER_INIT_STATUS_OK)
+            {
+                if(InitFlac())
+                {
+                    // all ok
+                    return;
+                }
+
+                FLAC__stream_decoder_finish(flacFile);
+            }
+            FLAC__stream_decoder_delete(flacFile);
+            flacFile = NULL;
+        }
+    }
+
+    virtual ~flacStream()
+    {
+        if(flacFile)
+        {
+            FLAC__stream_decoder_finish(flacFile);
+            FLAC__stream_decoder_delete(flacFile);
+            flacFile = NULL;
+        }
+    }
+
+private:
+    bool InitFlac()
+    {
+        // We need to decode some data to be able to get the channel count, bit
+        // depth, and sample rate. It also ensures the file has FLAC data, as
+        // the FLAC__stream_decoder_init_* functions can succeed on non-FLAC
+        // Ogg files.
+        outBytes = NULL;
+        outMax = 0;
+        outLen = 0;
+        while(initialData.size() == 0)
+        {
+            if(FLAC__stream_decoder_process_single(flacFile) == false ||
+               FLAC__stream_decoder_get_state(flacFile) == FLAC__STREAM_DECODER_END_OF_STREAM)
+                break;
+        }
+
+        if(initialData.size() > 0)
+            return true;
+        return false;
+    }
+
+
+    template<ALuint shift, ALint offset, typename T>
+    static void CopySamples(T *data, const FLAC__int32 *const buffer[], ALuint off, ALuint todo, ALuint channels)
+    {
+        for(ALuint i = 0;i < todo;i++)
+        {
+            for(ALuint c = 0;c < channels;c++)
+                *(data++) = (buffer[c][off+i]>>shift) + offset;
+        }
+    }
+
+    template<ALuint bits>
+    static void CopySamplesFloat(ALfloat *data, const FLAC__int32 *const buffer[], ALuint off, ALuint todo, ALuint channels)
+    {
+        for(ALuint i = 0;i < todo;i++)
+        {
+            for(ALuint c = 0;c < channels;c++)
+                *(data++) = buffer[c][off+i] * (1./((1u<<(bits-1))-1));
+        }
+    }
+
+    static FLAC__StreamDecoderWriteStatus WriteCallback(const FLAC__StreamDecoder*, const FLAC__Frame *frame, const FLAC__int32 *const buffer[], void *client_data)
+    {
+        flacStream *self = static_cast<flacStream*>(client_data);
+
+        if(self->format == AL_NONE)
+        {
+            ALuint bps = frame->header.bits_per_sample;
+            if(bps == 24 || bps == 32)
+            {
+                self->format = GetSampleFormat(frame->header.channels, 32, true);
+                if(self->format != AL_NONE)
+                {
+                    self->useFloat = AL_TRUE;
+                    bps = 32;
+                }
+                else bps = 16;
+            }
+            if(self->format == AL_NONE)
+                self->format = GetSampleFormat(frame->header.channels, bps, false);
+            self->blockAlign = frame->header.channels * bps/8;
+            self->samplerate = frame->header.sample_rate;
+        }
+
+        ALubyte *data = self->outBytes + self->outLen;
+        ALuint todo = std::min<ALuint>((self->outMax-self->outLen) / self->blockAlign,
+                                       frame->header.blocksize);
+        if(frame->header.bits_per_sample == 8)
+            CopySamples<0,128>((ALubyte*)data, buffer, 0,
+                               todo, frame->header.channels);
+        else if(frame->header.bits_per_sample == 16)
+            CopySamples<0,0>((ALshort*)data, buffer, 0,
+                             todo, frame->header.channels);
+        else if(frame->header.bits_per_sample == 24)
+        {
+            if(self->useFloat)
+                CopySamplesFloat<24>((ALfloat*)data, buffer, 0,
+                                     todo, frame->header.channels);
+            else
+                CopySamples<8,0>((ALshort*)data, buffer, 0,
+                                 todo, frame->header.channels);
+        }
+        else if(frame->header.bits_per_sample == 32)
+        {
+            if(self->useFloat)
+                CopySamplesFloat<32>((ALfloat*)data, buffer, 0,
+                                     todo, frame->header.channels);
+            else
+                CopySamples<16,0>((ALshort*)data, buffer, 0,
+                                  todo, frame->header.channels);
+        }
+        self->outLen += self->blockAlign * todo;
+
+        if(todo < frame->header.blocksize)
+        {
+            ALuint offset = todo;
+            todo = frame->header.blocksize - todo;
+
+            ALuint blocklen = todo * self->blockAlign;
+            ALuint start = self->initialData.size();
+
+            self->initialData.resize(start+blocklen);
+            data = &self->initialData[start];
+
+            if(frame->header.bits_per_sample == 8)
+                CopySamples<0,128>((ALubyte*)data, buffer, offset,
+                                   todo, frame->header.channels);
+            else if(frame->header.bits_per_sample == 16)
+                CopySamples<0,0>((ALshort*)data, buffer, offset,
+                                 todo, frame->header.channels);
+            else if(frame->header.bits_per_sample == 24)
+            {
+                if(self->useFloat)
+                    CopySamplesFloat<24>((ALfloat*)data, buffer, offset,
+                                         todo, frame->header.channels);
+                else
+                    CopySamples<8,0>((ALshort*)data, buffer, offset,
+                                     todo, frame->header.channels);
+            }
+            else if(frame->header.bits_per_sample == 32)
+            {
+                if(self->useFloat)
+                    CopySamplesFloat<32>((ALfloat*)data, buffer, offset,
+                                         todo, frame->header.channels);
+                else
+                    CopySamples<16,0>((ALshort*)data, buffer, offset,
+                                      todo, frame->header.channels);
+            }
+        }
+
+        return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
+    }
+    static void MetadataCallback(const FLAC__StreamDecoder*,const FLAC__StreamMetadata*,void*)
+    {
+    }
+    static void ErrorCallback(const FLAC__StreamDecoder*,FLAC__StreamDecoderErrorStatus,void*)
+    {
+    }
+
+    static FLAC__StreamDecoderReadStatus ReadCallback(const FLAC__StreamDecoder*, FLAC__byte buffer[], size_t *bytes, void *client_data)
+    {
+        std::istream *stream = static_cast<flacStream*>(client_data)->fstream;
+        stream->clear();
+
+        if(*bytes <= 0)
+            return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
+
+        stream->read(reinterpret_cast<char*>(buffer), *bytes);
+        *bytes = stream->gcount();
+        if(*bytes == 0 && stream->eof())
+            return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
+
+        return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
+    }
+    static FLAC__StreamDecoderSeekStatus SeekCallback(const FLAC__StreamDecoder*, FLAC__uint64 absolute_byte_offset, void *client_data)
+    {
+        std::istream *stream = static_cast<flacStream*>(client_data)->fstream;
+        stream->clear();
+
+        if(!stream->seekg(absolute_byte_offset))
+            return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
+        return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
+    }
+    static FLAC__StreamDecoderTellStatus TellCallback(const FLAC__StreamDecoder*, FLAC__uint64 *absolute_byte_offset, void *client_data)
+    {
+        std::istream *stream = static_cast<flacStream*>(client_data)->fstream;
+        stream->clear();
+
+        *absolute_byte_offset = stream->tellg();
+        return FLAC__STREAM_DECODER_TELL_STATUS_OK;
+    }
+    static FLAC__StreamDecoderLengthStatus LengthCallback(const FLAC__StreamDecoder*, FLAC__uint64 *stream_length, void *client_data)
+    {
+        std::istream *stream = static_cast<flacStream*>(client_data)->fstream;
+        stream->clear();
+
+        std::streampos pos = stream->tellg();
+        if(stream->seekg(0, std::ios_base::end))
+        {
+            *stream_length = stream->tellg();
+            stream->seekg(pos);
+        }
+
+        if(!stream->good())
+            return FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR;
+        return FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
+    }
+    static FLAC__bool EofCallback(const FLAC__StreamDecoder*, void *client_data)
+    {
+        std::istream *stream = static_cast<flacStream*>(client_data)->fstream;
+        return (stream->eof()) ? true : false;
+    }
+};
+// Priority = 1, so it's preferred over libsndfile
+static DecoderDecl<flacStream,1> flacStream_decoder;
+Decoder &alure_init_flac(void)
+{ return flacStream_decoder; }
diff --git a/src/codec_fluidsynth.cpp b/src/codec_fluidsynth.cpp
new file mode 100644 (file)
index 0000000..a5885e0
--- /dev/null
@@ -0,0 +1,679 @@
+/*
+ * ALURE  OpenAL utility library
+ * Copyright (c) 2009-2010 by Chris Robinson.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "config.h"
+
+#include "main.h"
+
+#include <string.h>
+#include <assert.h>
+#ifdef _WIN32
+#include <io.h>
+#endif
+
+#include <istream>
+
+#include <fluidsynth.h>
+
+
+#ifdef DYNLOAD
+static void *fsynth_handle;
+#define MAKE_FUNC(x) static typeof(x)* p##x
+MAKE_FUNC(fluid_settings_setstr);
+MAKE_FUNC(fluid_synth_program_change);
+MAKE_FUNC(fluid_synth_sfload);
+MAKE_FUNC(fluid_settings_setnum);
+MAKE_FUNC(fluid_synth_sysex);
+MAKE_FUNC(fluid_synth_cc);
+MAKE_FUNC(fluid_synth_pitch_bend);
+MAKE_FUNC(fluid_synth_channel_pressure);
+MAKE_FUNC(fluid_synth_write_float);
+MAKE_FUNC(new_fluid_synth);
+MAKE_FUNC(delete_fluid_settings);
+MAKE_FUNC(delete_fluid_synth);
+MAKE_FUNC(fluid_synth_program_reset);
+MAKE_FUNC(fluid_settings_setint);
+MAKE_FUNC(new_fluid_settings);
+MAKE_FUNC(fluid_synth_write_s16);
+MAKE_FUNC(fluid_synth_noteoff);
+MAKE_FUNC(fluid_synth_sfunload);
+MAKE_FUNC(fluid_synth_noteon);
+#undef MAKE_FUNC
+
+#define fluid_settings_setstr pfluid_settings_setstr
+#define fluid_synth_program_change pfluid_synth_program_change
+#define fluid_synth_sfload pfluid_synth_sfload
+#define fluid_settings_setnum pfluid_settings_setnum
+#define fluid_synth_sysex pfluid_synth_sysex
+#define fluid_synth_cc pfluid_synth_cc
+#define fluid_synth_pitch_bend pfluid_synth_pitch_bend
+#define fluid_synth_channel_pressure pfluid_synth_channel_pressure
+#define fluid_synth_write_float pfluid_synth_write_float
+#define new_fluid_synth pnew_fluid_synth
+#define delete_fluid_settings pdelete_fluid_settings
+#define delete_fluid_synth pdelete_fluid_synth
+#define fluid_synth_program_reset pfluid_synth_program_reset
+#define fluid_settings_setint pfluid_settings_setint
+#define new_fluid_settings pnew_fluid_settings
+#define fluid_synth_write_s16 pfluid_synth_write_s16
+#define fluid_synth_noteoff pfluid_synth_noteoff
+#define fluid_synth_sfunload pfluid_synth_sfunload
+#define fluid_synth_noteon pfluid_synth_noteon
+#else
+#define fsynth_handle 1
+#endif
+
+
+struct fluidStream : public alureStream {
+private:
+    static const ALubyte MIDI_CHANNEL_MASK = 0x0F;
+    static const ALubyte MIDI_EVENT_MASK   = 0xF0;
+
+    static const ALubyte MIDI_NOTEOFF    = 0x80;    // + note + velocity
+    static const ALubyte MIDI_NOTEON     = 0x90;    // + note + velocity
+    static const ALubyte MIDI_POLYPRESS  = 0xA0;    // + pressure (2 bytes)
+    static const ALubyte MIDI_CTRLCHANGE = 0xB0;    // + ctrl + value
+    static const ALubyte MIDI_PRGMCHANGE = 0xC0;    // + new patch
+    static const ALubyte MIDI_CHANPRESS  = 0xD0;    // + pressure (1 byte)
+    static const ALubyte MIDI_PITCHBEND  = 0xE0;    // + pitch bend (2 bytes)
+    static const ALubyte MIDI_SPECIAL    = 0xF0;    // Special event
+
+    static const ALubyte MIDI_SYSEX    = 0xF0;      // SysEx begin
+    static const ALubyte MIDI_SYSEXEND = 0xF7;      // SysEx end
+    static const ALubyte MIDI_SONGPOS  = 0xF2;      // Song position
+    static const ALubyte MIDI_SONGSEL  = 0xF3;      // Song select
+    static const ALubyte MIDI_META     = 0xFF;      // Meta event begin
+
+    static const ALubyte MIDI_META_EOT   = 0x2F;    // End-of-track
+    static const ALubyte MIDI_META_TEMPO = 0x51;    // Tempo change
+
+    struct MidiTrack {
+        std::vector<ALubyte> data;
+        size_t Offset;
+        ALubyte LastEvent;
+        ALdouble SamplesLeft;
+
+        MidiTrack() : Offset(0), LastEvent(0), SamplesLeft(0.)
+        { }
+        MidiTrack(const MidiTrack &rhs)
+          : data(rhs.data), Offset(rhs.Offset), LastEvent(rhs.LastEvent),
+            SamplesLeft(rhs.SamplesLeft)
+        { }
+
+        void Reset()
+        {
+            Offset = 0;
+            LastEvent = 0;
+            SamplesLeft = 0.;
+        }
+
+        const MidiTrack& operator=(const MidiTrack &rhs)
+        {
+            data = rhs.data;
+            Offset = rhs.Offset;
+            LastEvent = rhs.LastEvent;
+            SamplesLeft = rhs.SamplesLeft;
+            return *this;
+        }
+
+        unsigned long ReadVarLen()
+        {
+            if(Offset >= data.size())
+                return 0;
+
+            unsigned long len = data[Offset]&0x7F;
+            while((data[Offset]&0x80))
+            {
+                if(++Offset >= data.size())
+                    return 0;
+                len = (len<<7) | (data[Offset]&0x7F);
+            }
+            Offset++;
+
+            return len;
+        }
+    };
+
+    ALuint Divisions;
+    std::vector<MidiTrack> Tracks;
+
+    ALenum format;
+    ALsizei sampleRate;
+    ALdouble samplesPerTick;
+
+    fluid_settings_t *fluidSettings;
+    fluid_synth_t *fluidSynth;
+    int fontID;
+    bool doFontLoad;
+
+public:
+#ifdef DYNLOAD
+    static void Init()
+    {
+#ifdef _WIN32
+#define FLUIDSYNTH_LIB "libfluidsynth.dll"
+#elif defined(__APPLE__)
+#define FLUIDSYNTH_LIB "libfluidsynth.1.dylib"
+#else
+#define FLUIDSYNTH_LIB "libfluidsynth.so.1"
+#endif
+        fsynth_handle = OpenLib(FLUIDSYNTH_LIB);
+        if(!fsynth_handle) return;
+
+        LOAD_FUNC(fsynth_handle, fluid_settings_setstr);
+        LOAD_FUNC(fsynth_handle, fluid_synth_program_change);
+        LOAD_FUNC(fsynth_handle, fluid_synth_sfload);
+        LOAD_FUNC(fsynth_handle, fluid_settings_setnum);
+        LOAD_FUNC(fsynth_handle, fluid_synth_sysex);
+        LOAD_FUNC(fsynth_handle, fluid_synth_cc);
+        LOAD_FUNC(fsynth_handle, fluid_synth_pitch_bend);
+        LOAD_FUNC(fsynth_handle, fluid_synth_channel_pressure);
+        LOAD_FUNC(fsynth_handle, fluid_synth_write_float);
+        LOAD_FUNC(fsynth_handle, new_fluid_synth);
+        LOAD_FUNC(fsynth_handle, delete_fluid_settings);
+        LOAD_FUNC(fsynth_handle, delete_fluid_synth);
+        LOAD_FUNC(fsynth_handle, fluid_synth_program_reset);
+        LOAD_FUNC(fsynth_handle, fluid_settings_setint);
+        LOAD_FUNC(fsynth_handle, new_fluid_settings);
+        LOAD_FUNC(fsynth_handle, fluid_synth_write_s16);
+        LOAD_FUNC(fsynth_handle, fluid_synth_noteoff);
+        LOAD_FUNC(fsynth_handle, fluid_synth_sfunload);
+        LOAD_FUNC(fsynth_handle, fluid_synth_noteon);
+    }
+    static void Deinit()
+    {
+        if(fsynth_handle)
+            CloseLib(fsynth_handle);
+        fsynth_handle = NULL;
+    }
+#else
+    static void Init() { }
+    static void Deinit() { }
+#endif
+
+    virtual bool IsValid()
+    { return fluidSynth != NULL; }
+
+    virtual bool GetFormat(ALenum *fmt, ALuint *frequency, ALuint *blockalign)
+    {
+        if(format == AL_NONE)
+        {
+            format = GetSampleFormat(2, 32, true);
+            if(format == AL_NONE)
+                format = AL_FORMAT_STEREO16;
+        }
+        *fmt = format;
+        *frequency = sampleRate;
+        *blockalign = 2 * ((format==AL_FORMAT_STEREO16) ? sizeof(ALshort) :
+                                                          sizeof(ALfloat));
+        return true;
+    }
+
+    virtual ALuint GetData(ALubyte *data, ALuint bytes)
+    {
+        ALuint ret;
+
+        if(doFontLoad)
+        {
+            doFontLoad = false;
+            const char *soundfont = getenv("FLUID_SOUNDFONT");
+            if(soundfont && soundfont[0])
+                fontID = fluid_synth_sfload(fluidSynth, soundfont, true);
+        }
+
+        if(format == AL_FORMAT_STEREO16)
+        {
+            ALshort *ptr = reinterpret_cast<ALshort*>(data);
+            ret = FillBuffer(ptr, bytes/2/sizeof(ALshort));
+            ret *= 2 * sizeof(ALshort);
+        }
+        else
+        {
+            ALfloat *ptr = reinterpret_cast<ALfloat*>(data);
+            ret = FillBuffer(ptr, bytes/2/sizeof(ALfloat));
+            ret *= 2 * sizeof(ALfloat);
+        }
+
+        return ret;
+    }
+
+    virtual bool Rewind()
+    {
+        for(std::vector<MidiTrack>::iterator i = Tracks.begin(), end = Tracks.end();i != end;i++)
+        {
+            i->Reset();
+            unsigned long val = i->ReadVarLen();
+            i->SamplesLeft += val * samplesPerTick;
+        }
+        fluid_synth_program_reset(fluidSynth);
+        UpdateTempo(500000);
+        return true;
+    }
+
+    virtual bool SetPatchset(const char *sfont)
+    {
+        if(UsingSTDIO)
+        {
+            int newid = fluid_synth_sfload(fluidSynth, sfont, true);
+            if(newid == FLUID_FAILED)
+            {
+                SetError("Failed to load soundfont");
+                return false;
+            }
+
+            if(fontID != FLUID_FAILED)
+                fluid_synth_sfunload(fluidSynth, fontID, true);
+            fontID = newid;
+            doFontLoad = false;
+            return true;
+        }
+
+        /* FluidSynth has no way to load a soundfont using IO callbacks. So we
+         * have to copy the specified file using the callbacks to a regular
+         * file that FluidSynth can open. */
+        int newid = FLUID_FAILED;
+        InStream istream(sfont);
+        if(istream.fail())
+        {
+            SetError("Failed to open file");
+            return false;
+        }
+
+        /* First, get a temp filename */
+        const char *str = getenv("TEMP");
+        if(!str || !str[0]) str = getenv("TMP");
+#ifdef _WIN32
+        if(!str || !str[0]) str = ".";
+#else
+        if(!str || !str[0]) str = "/tmp";
+#endif
+        std::string fname = str;
+        fname += "/alure-sfont-XXXXXX";
+
+        for(size_t i = 0;i < fname.size();i++)
+        {
+            if(fname[i] == '\\')
+                fname[i] = '/';
+        }
+
+        std::vector<char> tmpfname(fname.begin(), fname.end());
+        tmpfname.push_back(0);
+
+        /* Open a temp file */
+        int fd = -1;
+        FILE *file;
+#ifdef _WIN32
+        if(mktemp(&tmpfname[0]) == NULL || (file=fopen(&tmpfname[0], "wb")) == NULL)
+#else
+        if((fd=mkstemp(&tmpfname[0])) == -1 || (file=fdopen(fd, "wb")) == NULL)
+#endif
+        {
+            if(fd >= 0)
+            {
+                close(fd);
+                remove(&tmpfname[0]);
+            }
+            SetError("Failed to create temp file");
+            return false;
+        }
+
+        bool copyok = false;
+        char buf[4096];
+        size_t got;
+        do {
+            istream.read(buf, sizeof(buf));
+            if((got=istream.gcount()) == 0)
+            {
+                copyok = true;
+                break;
+            }
+        } while(fwrite(buf, 1, got, file) == got);
+
+        if(copyok)
+        {
+            fflush(file);
+            newid = fluid_synth_sfload(fluidSynth, &tmpfname[0], true);
+        }
+
+        fclose(file);
+        remove(&tmpfname[0]);
+
+        if(!copyok)
+        {
+            SetError("Failed to copy file");
+            return false;
+        }
+
+        if(newid == FLUID_FAILED)
+        {
+            SetError("Failed to load soundfont");
+            return false;
+        }
+
+        if(fontID != FLUID_FAILED)
+            fluid_synth_sfunload(fluidSynth, fontID, true);
+        fontID = newid;
+        doFontLoad = false;
+
+        return true;
+    }
+
+    fluidStream(std::istream *_fstream)
+      : alureStream(_fstream), Divisions(100),
+        format(AL_NONE), sampleRate(48000), samplesPerTick(1.),
+        fluidSettings(NULL), fluidSynth(NULL), fontID(FLUID_FAILED),
+        doFontLoad(true)
+    {
+        if(!fsynth_handle) return;
+
+        ALCdevice *device = alcGetContextsDevice(alcGetCurrentContext());
+        if(device) alcGetIntegerv(device, ALC_FREQUENCY, 1, &sampleRate);
+
+        char hdr[4];
+        if(!fstream->read(hdr, 4))
+            return;
+
+        if(memcmp(hdr, "MThd", 4) == 0)
+        {
+            ALuint len = read_be32(fstream);
+            if(len != 6)
+                return;
+
+            int type = read_be16(fstream);
+            if(type != 0 && type != 1)
+                return;
+
+            ALuint numtracks = read_be16(fstream);
+
+            Divisions = read_be16(fstream);
+            UpdateTempo(500000);
+
+            Tracks.resize(numtracks);
+            for(std::vector<MidiTrack>::iterator i = Tracks.begin(), end = Tracks.end();i != end;i++)
+            {
+                if(!fstream->read(hdr, 4) || memcmp(hdr, "MTrk", 4) != 0)
+                    return;
+
+                ALint len = read_be32(fstream);
+                i->data.resize(len);
+                if(!fstream->read(reinterpret_cast<char*>(&i->data[0]), len) ||
+                   fstream->gcount() != len)
+                    return;
+
+                unsigned long val = i->ReadVarLen();
+                i->SamplesLeft += val * samplesPerTick;
+            }
+            SetupSynth();
+        }
+    }
+
+    virtual ~fluidStream()
+    {
+        if(fontID != FLUID_FAILED)
+            fluid_synth_sfunload(fluidSynth, fontID, true);
+        fontID = FLUID_FAILED;
+
+        if(fluidSynth != NULL)
+            delete_fluid_synth(fluidSynth);
+        fluidSynth = NULL;
+
+        if(fluidSettings != NULL)
+            delete_fluid_settings(fluidSettings);
+        fluidSettings = NULL;
+    }
+
+private:
+    template<typename T>
+    ALuint FillBuffer(T *Buffer, ALuint BufferSamples)
+    {
+        ALuint SamplesInBuffer = 0;
+        while(SamplesInBuffer < BufferSamples)
+        {
+            // Check if any tracks are still playing and how many samples are waiting to render
+            size_t TracksPlaying = 0;
+            ALuint SamplesToDo = BufferSamples - SamplesInBuffer;
+            for(std::vector<MidiTrack>::iterator i = Tracks.begin(),
+                                                 end = Tracks.end();i != end;i++)
+            {
+                if(i->Offset < i->data.size())
+                {
+                    SamplesToDo = std::min<ALuint>(SamplesToDo, i->SamplesLeft);
+                    TracksPlaying++;
+                }
+            }
+            if(TracksPlaying == 0)
+                break;
+
+            if(SamplesToDo == 0)
+            {
+                ProcessMidi();
+                continue;
+            }
+
+            // Render samples
+            WriteSamples(SamplesToDo, Buffer);
+            Buffer += SamplesToDo*2;
+            SamplesInBuffer += SamplesToDo;
+
+            for(std::vector<MidiTrack>::iterator i = Tracks.begin(),
+                                                 end = Tracks.end();i != end;i++)
+            {
+                if(i->Offset < i->data.size())
+                    i->SamplesLeft -= SamplesToDo;
+            }
+        }
+
+        return SamplesInBuffer;
+    }
+
+    void WriteSamples(ALuint count, short *buffer)
+    { fluid_synth_write_s16(fluidSynth, count, buffer, 0, 2, buffer, 1, 2); }
+    void WriteSamples(ALuint count, float *buffer)
+    { fluid_synth_write_float(fluidSynth, count, buffer, 0, 2, buffer, 1, 2); }
+
+    void ProcessMidi()
+    {
+        ALuint newtempo = 0;
+
+        // Process more events
+        std::vector<MidiTrack>::iterator i=Tracks.begin(), end=Tracks.end();
+        while(i != end)
+        {
+            if(i->Offset >= i->data.size() || i->SamplesLeft >= 1.)
+            {
+                i++;
+                continue;
+            }
+
+            if(i->data.size() - i->Offset < 3)
+            {
+                i->Offset = i->data.size();
+                i++;
+                continue;
+            }
+
+            ALubyte event = i->data[i->Offset++];
+            ALubyte parm1, parm2;
+            if(!(event&0x80))
+            {
+                event = i->LastEvent;
+                i->Offset--;
+            }
+            if((event&MIDI_EVENT_MASK) != MIDI_SPECIAL)
+                i->LastEvent = event;
+            parm1 = i->data[i->Offset];
+            parm2 = i->data[i->Offset+1];
+
+            int channel = event&MIDI_CHANNEL_MASK;
+            switch(event&MIDI_EVENT_MASK)
+            {
+                case MIDI_NOTEOFF:
+                    fluid_synth_noteoff(fluidSynth, channel, parm1);
+                    i->Offset += 2;
+                    break;
+                case MIDI_NOTEON:
+                    fluid_synth_noteon(fluidSynth, channel, parm1, parm2);
+                    i->Offset += 2;
+                    break;
+                case MIDI_POLYPRESS:
+                    i->Offset += 2;
+                    break;
+
+                case MIDI_CTRLCHANGE:
+                    fluid_synth_cc(fluidSynth, channel, parm1, parm2);
+                    i->Offset += 2;
+                    break;
+                case MIDI_PRGMCHANGE:
+                    fluid_synth_program_change(fluidSynth, channel, parm1);
+                    i->Offset += 1;
+                    break;
+
+                case MIDI_CHANPRESS:
+                    fluid_synth_channel_pressure(fluidSynth, channel, parm1);
+                    i->Offset += 1;
+                    break;
+
+                case MIDI_PITCHBEND:
+                    fluid_synth_pitch_bend(fluidSynth, channel, (parm1&0x7F) | ((parm2&0x7F)<<7));
+                    i->Offset += 2;
+                    break;
+
+                case MIDI_SPECIAL:
+                    switch(event)
+                    {
+                        case MIDI_SYSEX:
+                        {
+                            unsigned long len = i->ReadVarLen();
+                            if(i->data.size() - i->Offset < len)
+                            {
+                                i->Offset = i->data.size();
+                                break;
+                            }
+
+                            if(i->data[i->Offset+len-1] == MIDI_SYSEXEND)
+                            {
+                                char *data = reinterpret_cast<char*>(&i->data[i->Offset]);
+                                fluid_synth_sysex(fluidSynth, data, len-1, NULL, NULL, NULL, false);
+                            }
+                            i->Offset += len;
+                            break;
+                        }
+                        case MIDI_SYSEXEND:
+                        {
+                            unsigned long len = i->ReadVarLen();
+                            if(i->data.size() - i->Offset < len)
+                            {
+                                i->Offset = i->data.size();
+                                break;
+                            }
+                            i->Offset += len;
+                            break;
+                        }
+
+                        case MIDI_SONGPOS:
+                            i->Offset += 2;
+                            break;
+
+                        case MIDI_SONGSEL:
+                            i->Offset += 1;
+                            break;
+
+                        case MIDI_META:
+                        {
+                            ALubyte metatype = i->data[i->Offset++];
+                            unsigned long val = i->ReadVarLen();
+
+                            if(i->data.size() - i->Offset < val)
+                            {
+                                i->Offset = i->data.size();
+                                break;
+                            }
+
+                            if(metatype == MIDI_META_EOT)
+                            {
+                                i->Offset = i->data.size();
+                                break;
+                            }
+
+                            if(metatype == MIDI_META_TEMPO && val >= 3)
+                            {
+                                newtempo = (i->data[i->Offset] << 16) |
+                                           (i->data[i->Offset+1] << 8) |
+                                           (i->data[i->Offset+2]);
+                            }
+
+                            i->Offset += val;
+                            break;
+                        }
+
+                        default:
+                            /* The rest of the special events don't have any
+                             * data bytes */
+                            break;
+                    }
+                    break;
+
+                default:
+                    /* Shouldn't ever get to here */
+                    break;
+            }
+
+            unsigned long val = i->ReadVarLen();
+            i->SamplesLeft += val * samplesPerTick;
+        }
+        if(newtempo)
+            UpdateTempo(newtempo);
+    }
+
+    void UpdateTempo(ALuint tempo)
+    {
+        ALdouble sampletickrate = sampleRate / (1000000. / tempo) / Divisions;
+
+        for(std::vector<MidiTrack>::iterator i = Tracks.begin(),
+                                             end = Tracks.end();i != end;i++)
+        {
+            if(i->Offset >= i->data.size())
+                continue;
+            i->SamplesLeft = i->SamplesLeft / samplesPerTick * sampletickrate;
+        }
+        samplesPerTick = sampletickrate;
+    }
+
+    void SetupSynth()
+    {
+        fluidSettings = new_fluid_settings();
+        if(fluidSettings)
+        {
+            fluid_settings_setnum(fluidSettings, "synth.gain", 0.5);
+            fluid_settings_setstr(fluidSettings, "synth.reverb.active", "yes");
+            fluid_settings_setstr(fluidSettings, "synth.chorus.active", "yes");
+            fluid_settings_setint(fluidSettings, "synth.polyphony", 256);
+            fluid_settings_setnum(fluidSettings, "synth.sample-rate", (double)sampleRate);
+
+            fluidSynth = new_fluid_synth(fluidSettings);
+        }
+    }
+};
+static DecoderDecl<fluidStream,0> fluidStream_decoder;
+Decoder &alure_init_fluidsynth(void)
+{ return fluidStream_decoder; }
diff --git a/src/codec_modplug.cpp b/src/codec_modplug.cpp
new file mode 100644 (file)
index 0000000..816077c
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ * ALURE  OpenAL utility library
+ * Copyright (c) 2009-2010 by Chris Robinson.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "config.h"
+
+#include "main.h"
+
+#include <string.h>
+#include <assert.h>
+
+#include <istream>
+
+#include <libmodplug/modplug.h>
+
+
+#ifdef DYNLOAD
+static void *mod_handle;
+#define MAKE_FUNC(x) static typeof(x)* p##x
+MAKE_FUNC(ModPlug_Load);
+MAKE_FUNC(ModPlug_Unload);
+MAKE_FUNC(ModPlug_Read);
+MAKE_FUNC(ModPlug_SeekOrder);
+#undef MAKE_FUNC
+
+#define ModPlug_Load pModPlug_Load
+#define ModPlug_Unload pModPlug_Unload
+#define ModPlug_Read pModPlug_Read
+#define ModPlug_SeekOrder pModPlug_SeekOrder
+#else
+#define mod_handle 1
+#endif
+
+
+struct modStream : public alureStream {
+private:
+    ModPlugFile *modFile;
+    int lastOrder;
+
+public:
+#ifdef DYNLOAD
+    static void Init()
+    {
+#ifdef _WIN32
+#define MODPLUG_LIB "libmodplug.dll"
+#elif defined(__APPLE__)
+#define MODPLUG_LIB "libmodplug.1.dylib"
+#else
+#define MODPLUG_LIB "libmodplug.so.1"
+#endif
+        mod_handle = OpenLib(MODPLUG_LIB);
+        if(!mod_handle) return;
+
+        LOAD_FUNC(mod_handle, ModPlug_Load);
+        LOAD_FUNC(mod_handle, ModPlug_Unload);
+        LOAD_FUNC(mod_handle, ModPlug_Read);
+        LOAD_FUNC(mod_handle, ModPlug_SeekOrder);
+    }
+    static void Deinit()
+    {
+        if(mod_handle)
+            CloseLib(mod_handle);
+        mod_handle = NULL;
+    }
+#else
+    static void Init() { }
+    static void Deinit() { }
+#endif
+
+    virtual bool IsValid()
+    { return modFile != NULL; }
+
+    virtual bool GetFormat(ALenum *fmt, ALuint *frequency, ALuint *blockalign)
+    {
+        *fmt = AL_FORMAT_STEREO16;
+        *frequency = 44100;
+        *blockalign = 2 * sizeof(ALshort);
+        return true;
+    }
+
+    virtual ALuint GetData(ALubyte *data, ALuint bytes)
+    {
+        int ret = ModPlug_Read(modFile, data, bytes);
+        if(ret < 0) return 0;
+        return ret;
+    }
+
+    virtual bool Rewind()
+    { return SetOrder(lastOrder); }
+
+    virtual bool SetOrder(ALuint order)
+    {
+        std::vector<char> data(16384);
+        ALuint total = 0;
+        while(1)
+        {
+            fstream->read(&data[total], data.size()-total);
+            if(fstream->gcount() == 0) break;
+            total += fstream->gcount();
+            data.resize(total*2);
+        }
+        data.resize(total);
+
+        ModPlugFile *newMod = ModPlug_Load(&data[0], data.size());
+        if(!newMod)
+        {
+            SetError("Could not reload data");
+            return false;
+        }
+        ModPlug_Unload(modFile);
+        modFile = newMod;
+
+        // There seems to be no way to tell if the seek succeeds
+        ModPlug_SeekOrder(modFile, order);
+        lastOrder = order;
+
+        return true;
+    }
+
+    modStream(std::istream *_fstream)
+      : alureStream(_fstream), modFile(NULL), lastOrder(0)
+    {
+        if(!mod_handle) return;
+
+        std::vector<char> data(1024);
+        ALuint total = 0;
+
+        fstream->read(&data[total], data.size()-total);
+        total += fstream->gcount();
+        if(total < 32) return;
+
+        if(memcmp(&data[0], "Extended Module: ", 17) == 0 || /* XM */
+           (data[28] == 0x1A && data[29] == 0x10) || /* S3M */
+           memcmp(&data[0], "IMPM", 4) == 0) /* IT */
+        {
+            while(1)
+            {
+                data.resize(total*2);
+                fstream->read(&data[total], data.size()-total);
+                if(fstream->gcount() == 0) break;
+                total += fstream->gcount();
+            }
+            data.resize(total);
+
+            modFile = ModPlug_Load(&data[0], data.size());
+        }
+    }
+
+    virtual ~modStream()
+    {
+        if(modFile)
+            ModPlug_Unload(modFile);
+        modFile = NULL;
+    }
+};
+// Priority = -1, because mod loading can find false-positives
+static DecoderDecl<modStream,-1> modStream_decoder;
+Decoder &alure_init_modplug(void)
+{ return modStream_decoder; }
diff --git a/src/codec_mpg123.cpp b/src/codec_mpg123.cpp
new file mode 100644 (file)
index 0000000..72b9eed
--- /dev/null
@@ -0,0 +1,340 @@
+/*
+ * ALURE  OpenAL utility library
+ * Copyright (c) 2009-2010 by Chris Robinson.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "config.h"
+
+#include "main.h"
+
+#include <string.h>
+#include <assert.h>
+
+#include <istream>
+
+#include <mpg123.h>
+
+
+#ifdef DYNLOAD
+static void *mp123_handle;
+#define MAKE_FUNC(x) static typeof(x)* p##x
+MAKE_FUNC(mpg123_read);
+MAKE_FUNC(mpg123_init);
+MAKE_FUNC(mpg123_open_feed);
+MAKE_FUNC(mpg123_new);
+MAKE_FUNC(mpg123_delete);
+MAKE_FUNC(mpg123_feed);
+MAKE_FUNC(mpg123_exit);
+MAKE_FUNC(mpg123_getformat);
+MAKE_FUNC(mpg123_format_none);
+MAKE_FUNC(mpg123_decode);
+MAKE_FUNC(mpg123_format);
+#undef MAKE_FUNC
+
+#define mpg123_read pmpg123_read
+#define mpg123_init pmpg123_init
+#define mpg123_open_feed pmpg123_open_feed
+#define mpg123_new pmpg123_new
+#define mpg123_delete pmpg123_delete
+#define mpg123_feed pmpg123_feed
+#define mpg123_exit pmpg123_exit
+#define mpg123_getformat pmpg123_getformat
+#define mpg123_format_none pmpg123_format_none
+#define mpg123_decode pmpg123_decode
+#define mpg123_format pmpg123_format
+#else
+#define mp123_handle 1
+#endif
+
+
+struct mp3Stream : public alureStream {
+private:
+    mpg123_handle *mp3File;
+    long samplerate;
+    int channels;
+    ALenum format;
+    std::ios::pos_type dataStart;
+    std::ios::pos_type dataEnd;
+
+public:
+#ifdef DYNLOAD
+    static void Init()
+    {
+#ifdef _WIN32
+#define MPG123_LIB "libmpg123.dll"
+#elif defined(__APPLE__)
+#define MPG123_LIB "libmpg123.0.dylib"
+#else
+#define MPG123_LIB "libmpg123.so.0"
+#endif
+        mp123_handle = OpenLib(MPG123_LIB);
+        if(!mp123_handle) return;
+
+        LOAD_FUNC(mp123_handle, mpg123_read);
+        LOAD_FUNC(mp123_handle, mpg123_init);
+        LOAD_FUNC(mp123_handle, mpg123_open_feed);
+        LOAD_FUNC(mp123_handle, mpg123_new);
+        LOAD_FUNC(mp123_handle, mpg123_delete);
+        LOAD_FUNC(mp123_handle, mpg123_feed);
+        LOAD_FUNC(mp123_handle, mpg123_exit);
+        LOAD_FUNC(mp123_handle, mpg123_getformat);
+        LOAD_FUNC(mp123_handle, mpg123_format_none);
+        LOAD_FUNC(mp123_handle, mpg123_decode);
+        LOAD_FUNC(mp123_handle, mpg123_format);
+        pmpg123_init();
+    }
+    static void Deinit()
+    {
+        if(mp123_handle)
+        {
+            pmpg123_exit();
+            CloseLib(mp123_handle);
+        }
+        mp123_handle = NULL;
+    }
+#else
+    static void Init() { }
+    static void Deinit() { }
+#endif
+
+    virtual bool IsValid()
+    { return mp3File != NULL; }
+
+    virtual bool GetFormat(ALenum *fmt, ALuint *frequency, ALuint *blockalign)
+    {
+        *fmt = format;
+        *frequency = samplerate;
+        *blockalign = channels*2;
+        return true;
+    }
+
+    virtual ALuint GetData(ALubyte *data, ALuint bytes)
+    {
+        if(!mp3File)
+            return 0;
+
+        ALuint amt = 0;
+        while(bytes > 0)
+        {
+            size_t got = 0;
+            int ret = mpg123_read(mp3File, data, bytes, &got);
+
+            bytes -= got;
+            data += got;
+            amt += got;
+
+            if(ret == MPG123_NEW_FORMAT)
+            {
+                mpg123_delete(mp3File);
+                mp3File = NULL;
+                break;
+            }
+            if(ret == MPG123_NEED_MORE)
+            {
+                unsigned char data[4096];
+                ALint insize = std::min<ALint>(sizeof(data),
+                                               (dataEnd-fstream->tellg()));
+                if(insize > 0)
+                {
+                    fstream->read((char*)data, insize);
+                    insize = fstream->gcount();
+                }
+                if(insize > 0 && mpg123_feed(mp3File, data, insize) == MPG123_OK)
+                    continue;
+            }
+            if(got == 0)
+                break;
+        }
+        return amt;
+    }
+
+    virtual bool Rewind()
+    {
+        fstream->clear();
+        std::ios::pos_type oldpos = fstream->tellg();
+        fstream->seekg(dataStart);
+
+        mpg123_handle *newFile = mpg123_new(NULL, NULL);
+        if(mpg123_open_feed(newFile) == MPG123_OK)
+        {
+            unsigned char data[4096];
+            long newrate;
+            int newchans;
+            int enc;
+
+            ALuint amt, total = 0;
+            int ret = MPG123_OK;
+            do {
+                amt = std::min<ALint>(sizeof(data),
+                                      (dataEnd-fstream->tellg()));
+                fstream->read((char*)data, amt);
+                amt = fstream->gcount();
+                if(amt == 0)  break;
+                total += amt;
+                ret = mpg123_decode(newFile, data, amt, NULL, 0, NULL);
+            } while(ret == MPG123_NEED_MORE && total < 64*1024);
+
+            if(ret == MPG123_NEW_FORMAT &&
+               mpg123_getformat(newFile, &newrate, &newchans, &enc) == MPG123_OK)
+            {
+                if(mpg123_format_none(newFile) == MPG123_OK &&
+                   mpg123_format(newFile, samplerate, channels, MPG123_ENC_SIGNED_16) == MPG123_OK)
+                {
+                    // All OK
+                    if(mp3File)
+                        mpg123_delete(mp3File);
+                    mp3File = newFile;
+                    return true;
+                }
+            }
+            mpg123_delete(newFile);
+        }
+
+        fstream->seekg(oldpos);
+        SetError("Restart failed");
+        return false;
+    }
+
+    mp3Stream(std::istream *_fstream)
+      : alureStream(_fstream), mp3File(NULL), format(AL_NONE),
+        dataStart(0), dataEnd(0)
+    {
+        if(!mp123_handle) return;
+
+        if(!FindDataChunk())
+            return;
+
+        mp3File = mpg123_new(NULL, NULL);
+        if(mpg123_open_feed(mp3File) == MPG123_OK)
+        {
+            unsigned char data[4096];
+            int enc;
+
+            ALuint amt, total = 0;
+            int ret = MPG123_OK;
+            do {
+                amt = std::min<ALint>(sizeof(data),
+                                      (dataEnd-fstream->tellg()));
+                fstream->read((char*)data, amt);
+                amt = fstream->gcount();
+                if(amt == 0)  break;
+                total += amt;
+                ret = mpg123_decode(mp3File, data, amt, NULL, 0, NULL);
+            } while(ret == MPG123_NEED_MORE && total < 64*1024);
+
+            if(ret == MPG123_NEW_FORMAT &&
+               mpg123_getformat(mp3File, &samplerate, &channels, &enc) == MPG123_OK)
+            {
+                format = GetSampleFormat(channels, 16, false);
+                if(mpg123_format_none(mp3File) == MPG123_OK &&
+                   mpg123_format(mp3File, samplerate, channels, MPG123_ENC_SIGNED_16) == MPG123_OK)
+                {
+                    // All OK
+                    return;
+                }
+            }
+        }
+        mpg123_delete(mp3File);
+        mp3File = NULL;
+    }
+
+    virtual ~mp3Stream()
+    {
+        if(mp3File)
+            mpg123_delete(mp3File);
+        mp3File = NULL;
+    }
+
+private:
+    bool FindDataChunk()
+    {
+        ALubyte buffer[25];
+        int length;
+
+        if(!fstream->read(reinterpret_cast<char*>(buffer), 12))
+            return false;
+
+        if(memcmp(buffer, "RIFF", 4) != 0 || memcmp(buffer+8, "WAVE", 4) != 0)
+        {
+            dataStart = 0;
+
+            // Check for an ID3v2 tag, and skip it
+            if(memcmp(buffer, "ID3", 3) == 0 &&
+               buffer[3] <= 4 && buffer[4] != 0xff &&
+               (buffer[5]&0x0f) == 0 && (buffer[6]&0x80) == 0 &&
+               (buffer[7]&0x80) == 0 && (buffer[8]&0x80) == 0 &&
+               (buffer[9]&0x80) == 0)
+            {
+                dataStart = (buffer[6]<<21) | (buffer[7]<<14) |
+                            (buffer[8]<< 7) | (buffer[9]    );
+                dataStart += ((buffer[5]&0x10) ? 20 : 10);
+            }
+
+            if(fstream->seekg(0, std::ios_base::end))
+            {
+                dataEnd = fstream->tellg();
+                fstream->seekg(dataStart);
+            }
+            return fstream->good();
+        }
+
+        int type = 0;
+        while(1)
+        {
+            char tag[4];
+            if(!fstream->read(tag, 4))
+                break;
+
+            /* read chunk length */
+            length = read_le32(fstream);
+
+            if(memcmp(tag, "fmt ", 4) == 0 && length >= 16)
+            {
+                /* Data type (should be 0x0050 or 0x0055 for MP3 data) */
+                type = read_le16(fstream);
+                if(type != 0x0050 && type != 0x0055)
+                    break;
+                length -= 2;
+                /* Ignore the rest of the chunk. Everything we need is in the
+                 * data stream */
+            }
+            else if(memcmp(tag, "data", 4) == 0)
+            {
+                if(type == 0x0050 || type == 0x0055)
+                {
+                    dataStart = fstream->tellg();
+                    dataEnd = dataStart;
+                    dataEnd += length;
+                    return fstream->good();
+                }
+            }
+
+            fstream->seekg(length, std::ios_base::cur);
+        }
+
+        return false;
+    }
+};
+// Priority = -2, because mp3 loading can find false-positives, and interferes
+// with mod files
+static DecoderDecl<mp3Stream,-2> mp3Stream_decoder;
+Decoder &alure_init_mpg123(void)
+{ return mp3Stream_decoder; }
diff --git a/src/codec_sndfile.cpp b/src/codec_sndfile.cpp
new file mode 100644 (file)
index 0000000..203ab16
--- /dev/null
@@ -0,0 +1,197 @@
+/*
+ * ALURE  OpenAL utility library
+ * Copyright (c) 2009-2010 by Chris Robinson.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "config.h"
+
+#include "main.h"
+
+#include <string.h>
+#include <assert.h>
+
+#include <istream>
+
+#include <sndfile.h>
+
+
+#ifdef DYNLOAD
+static void *sndfile_handle;
+#define MAKE_FUNC(x) static typeof(x)* p##x
+MAKE_FUNC(sf_close);
+MAKE_FUNC(sf_open_virtual);
+MAKE_FUNC(sf_readf_short);
+MAKE_FUNC(sf_seek);
+#undef MAKE_FUNC
+
+#define sf_close psf_close
+#define sf_open_virtual psf_open_virtual
+#define sf_readf_short psf_readf_short
+#define sf_seek psf_seek
+#else
+#define sndfile_handle 1
+#endif
+
+
+struct sndStream : public alureStream {
+private:
+    SNDFILE *sndFile;
+    SF_INFO sndInfo;
+    ALenum format;
+
+public:
+#ifdef DYNLOAD
+    static void Init()
+    {
+#ifdef _WIN32
+#define SNDFILE_LIB "libsndfile-1.dll"
+#elif defined(__APPLE__)
+#define SNDFILE_LIB "libsndfile.1.dylib"
+#else
+#define SNDFILE_LIB "libsndfile.so.1"
+#endif
+        sndfile_handle = OpenLib(SNDFILE_LIB);
+        if(!sndfile_handle) return;
+
+        LOAD_FUNC(sndfile_handle, sf_close);
+        LOAD_FUNC(sndfile_handle, sf_open_virtual);
+        LOAD_FUNC(sndfile_handle, sf_readf_short);
+        LOAD_FUNC(sndfile_handle, sf_seek);
+    }
+    static void Deinit()
+    {
+        if(sndfile_handle)
+            CloseLib(sndfile_handle);
+        sndfile_handle = NULL;
+    }
+#else
+    static void Init() { }
+    static void Deinit() { }
+#endif
+
+    virtual bool IsValid()
+    { return sndFile != NULL; }
+
+    virtual bool GetFormat(ALenum *fmt, ALuint *frequency, ALuint *blockalign)
+    {
+        if(format == AL_NONE)
+            format = GetSampleFormat(sndInfo.channels, 16, false);
+        *fmt = format;
+        *frequency = sndInfo.samplerate;
+        *blockalign = sndInfo.channels*2;
+        return true;
+    }
+
+    virtual ALuint GetData(ALubyte *data, ALuint bytes)
+    {
+        const ALuint frameSize = 2*sndInfo.channels;
+        return sf_readf_short(sndFile, (short*)data, bytes/frameSize) * frameSize;
+    }
+
+    virtual bool Rewind()
+    {
+        if(sf_seek(sndFile, 0, SEEK_SET) != -1)
+            return true;
+
+        SetError("Seek failed");
+        return false;
+    }
+
+    virtual alureInt64 GetLength()
+    {
+        if(sndInfo.frames == -1)
+            return 0;
+        return sndInfo.frames;
+    }
+
+    sndStream(std::istream *_fstream)
+      : alureStream(_fstream), sndFile(NULL), format(AL_NONE)
+    {
+        memset(&sndInfo, 0, sizeof(sndInfo));
+
+        if(!sndfile_handle) return;
+
+        static SF_VIRTUAL_IO streamIO = {
+            get_filelen, seek,
+            read, write, tell
+        };
+        sndFile = sf_open_virtual(&streamIO, SFM_READ, &sndInfo, this);
+    }
+
+    virtual ~sndStream()
+    {
+        if(sndFile)
+            sf_close(sndFile);
+        sndFile = NULL;
+    }
+
+private:
+    // libSndFile iostream callbacks
+    static sf_count_t get_filelen(void *user_data)
+    {
+        std::istream *stream = static_cast<sndStream*>(user_data)->fstream;
+        stream->clear();
+
+        std::streampos len = -1;
+        std::streampos pos = stream->tellg();
+        if(stream->seekg(0, std::ios_base::end))
+        {
+            len = stream->tellg();
+            stream->seekg(pos);
+        }
+
+        return len;
+    }
+
+    static sf_count_t seek(sf_count_t offset, int whence, void *user_data)
+    {
+        std::istream *stream = static_cast<sndStream*>(user_data)->fstream;
+        stream->clear();
+
+        if((whence == SEEK_CUR && stream->seekg(offset, std::ios_base::cur)) ||
+           (whence == SEEK_SET && stream->seekg(offset, std::ios_base::beg)) ||
+           (whence == SEEK_END && stream->seekg(offset, std::ios_base::end)))
+            return stream->tellg();
+
+        return -1;
+    }
+
+    static sf_count_t read(void *ptr, sf_count_t count, void *user_data)
+    {
+        std::istream *stream = static_cast<sndStream*>(user_data)->fstream;
+        stream->clear();
+        stream->read(static_cast<char*>(ptr), count);
+        return stream->gcount();
+    }
+
+    static sf_count_t write(const void*, sf_count_t, void*)
+    { return -1; }
+
+    static sf_count_t tell(void *user_data)
+    {
+        std::istream *stream = static_cast<sndStream*>(user_data)->fstream;
+        stream->clear();
+        return stream->tellg();
+    }
+};
+static DecoderDecl<sndStream,0> sndStream_decoder;
+Decoder &alure_init_sndfile(void)
+{ return sndStream_decoder; }
diff --git a/src/codec_vorbisfile.cpp b/src/codec_vorbisfile.cpp
new file mode 100644 (file)
index 0000000..ef1ea60
--- /dev/null
@@ -0,0 +1,269 @@
+/*
+ * ALURE  OpenAL utility library
+ * Copyright (c) 2009-2010 by Chris Robinson.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "config.h"
+
+#include "main.h"
+
+#include <string.h>
+#include <assert.h>
+
+#include <istream>
+
+#ifdef HAS_VORBISIDEC
+#include <tremor/ivorbiscodec.h>
+#include <tremor/ivorbisfile.h>
+#else
+#include <vorbis/vorbisfile.h>
+#endif
+
+
+#ifdef DYNLOAD
+static void *vorbisfile_handle;
+#define MAKE_FUNC(x) static typeof(x)* p##x
+MAKE_FUNC(ov_clear);
+MAKE_FUNC(ov_info);
+MAKE_FUNC(ov_open_callbacks);
+MAKE_FUNC(ov_pcm_seek);
+MAKE_FUNC(ov_pcm_total);
+MAKE_FUNC(ov_read);
+#undef MAKE_FUNC
+
+#define ov_clear pov_clear
+#define ov_info pov_info
+#define ov_open_callbacks pov_open_callbacks
+#define ov_pcm_seek pov_pcm_seek
+#define ov_pcm_total pov_pcm_total
+#define ov_read pov_read
+#else
+#define vorbisfile_handle 1
+#endif
+
+
+struct oggStream : public alureStream {
+private:
+    OggVorbis_File oggFile;
+    vorbis_info *oggInfo;
+    int oggBitstream;
+    ALenum format;
+
+public:
+#ifdef DYNLOAD
+    static void Init()
+    {
+#ifdef HAS_VORBISIDEC
+#ifdef _WIN32
+#define VORBISFILE_LIB "vorbisidec.dll"
+#elif defined(__APPLE__)
+#define VORBISFILE_LIB "libvorbisidec.1.dylib"
+#else
+#define VORBISFILE_LIB "libvorbisidec.so.1"
+#endif
+#else
+#ifdef _WIN32
+#define VORBISFILE_LIB "vorbisfile.dll"
+#elif defined(__APPLE__)
+#define VORBISFILE_LIB "libvorbisfile.3.dylib"
+#else
+#define VORBISFILE_LIB "libvorbisfile.so.3"
+#endif
+#endif
+        vorbisfile_handle = OpenLib(VORBISFILE_LIB);
+        if(!vorbisfile_handle) return;
+
+        LOAD_FUNC(vorbisfile_handle, ov_clear);
+        LOAD_FUNC(vorbisfile_handle, ov_info);
+        LOAD_FUNC(vorbisfile_handle, ov_open_callbacks);
+        LOAD_FUNC(vorbisfile_handle, ov_pcm_seek);
+        LOAD_FUNC(vorbisfile_handle, ov_pcm_total);
+        LOAD_FUNC(vorbisfile_handle, ov_read);
+    }
+    static void Deinit()
+    {
+        if(vorbisfile_handle)
+            CloseLib(vorbisfile_handle);
+        vorbisfile_handle = NULL;
+    }
+#else
+    static void Init() { }
+    static void Deinit() { }
+#endif
+
+    virtual bool IsValid()
+    { return oggInfo != NULL; }
+
+    virtual bool GetFormat(ALenum *fmt, ALuint *frequency, ALuint *blockalign)
+    {
+        if(format == AL_NONE)
+            format = GetSampleFormat(oggInfo->channels, 16, false);
+        *fmt = format;
+        *frequency = oggInfo->rate;
+        *blockalign = oggInfo->channels*2;
+        return true;
+    }
+
+    virtual ALuint GetData(ALubyte *data, ALuint bytes)
+    {
+        ALuint got = 0;
+        while(bytes > 0)
+        {
+#ifdef HAS_VORBISIDEC
+            int res = ov_read(&oggFile, (char*)&data[got], bytes, &oggBitstream);
+#else
+            int res = ov_read(&oggFile, (char*)&data[got], bytes, BigEndian?1:0, 2, 1, &oggBitstream);
+#endif
+            if(res <= 0)
+                break;
+            bytes -= res;
+            got += res;
+        }
+        // 1, 2, and 4 channel files decode into the same channel order as
+        // OpenAL, however 6(5.1), 7(6.1), and 8(7.1) channel files need to be
+        // re-ordered
+        if(oggInfo->channels == 6)
+        {
+            ALshort *samples = (ALshort*)data;
+            for(ALuint i = 0;i < got/sizeof(ALshort);i+=6)
+            {
+                // OpenAL : FL, FR, FC, LFE, RL, RR
+                // Vorbis : FL, FC, FR,  RL, RR, LFE
+                swap(samples[i+1], samples[i+2]);
+                swap(samples[i+3], samples[i+5]);
+                swap(samples[i+4], samples[i+5]);
+            }
+        }
+        else if(oggInfo->channels == 7)
+        {
+            ALshort *samples = (ALshort*)data;
+            for(ALuint i = 0;i < got/sizeof(ALshort);i+=7)
+            {
+                // OpenAL : FL, FR, FC, LFE, RC, SL, SR
+                // Vorbis : FL, FC, FR,  SL, SR, RC, LFE
+                swap(samples[i+1], samples[i+2]);
+                swap(samples[i+3], samples[i+6]);
+                swap(samples[i+4], samples[i+6]);
+                swap(samples[i+5], samples[i+6]);
+            }
+        }
+        else if(oggInfo->channels == 8)
+        {
+            ALshort *samples = (ALshort*)data;
+            for(ALuint i = 0;i < got/sizeof(ALshort);i+=8)
+            {
+                // OpenAL : FL, FR, FC, LFE, RL, RR, SL, SR
+                // Vorbis : FL, FC, FR,  SL, SR, RL, RR, LFE
+                swap(samples[i+1], samples[i+2]);
+                swap(samples[i+3], samples[i+7]);
+                swap(samples[i+4], samples[i+5]);
+                swap(samples[i+5], samples[i+6]);
+                swap(samples[i+6], samples[i+7]);
+            }
+        }
+        return got;
+    }
+
+    virtual bool Rewind()
+    {
+        if(ov_pcm_seek(&oggFile, 0) == 0)
+            return true;
+
+        SetError("Seek failed");
+        return false;
+    }
+
+    virtual alureInt64 GetLength()
+    {
+        ogg_int64_t len = ov_pcm_total(&oggFile, oggBitstream);
+        if(len < 0) return 0;
+        return len;
+    }
+
+    oggStream(std::istream *_fstream)
+      : alureStream(_fstream), oggInfo(NULL), oggBitstream(0), format(AL_NONE)
+    {
+        if(!vorbisfile_handle) return;
+
+        const ov_callbacks streamIO = {
+            read, seek, close, tell
+        };
+
+        if(ov_open_callbacks(this, &oggFile, NULL, 0, streamIO) == 0)
+        {
+            oggInfo = ov_info(&oggFile, -1);
+            if(!oggInfo)
+                ov_clear(&oggFile);
+        }
+    }
+
+    virtual ~oggStream()
+    {
+        if(oggInfo)
+            ov_clear(&oggFile);
+        oggInfo = NULL;
+    }
+
+private:
+    // libVorbisFile iostream callbacks
+    static int seek(void *user_data, ogg_int64_t offset, int whence)
+    {
+        std::istream *stream = static_cast<oggStream*>(user_data)->fstream;
+        stream->clear();
+
+        if(whence == SEEK_CUR)
+            stream->seekg(offset, std::ios_base::cur);
+        else if(whence == SEEK_SET)
+            stream->seekg(offset, std::ios_base::beg);
+        else if(whence == SEEK_END)
+            stream->seekg(offset, std::ios_base::end);
+        else
+            return -1;
+
+        return stream->tellg();
+    }
+
+    static size_t read(void *ptr, size_t size, size_t nmemb, void *user_data)
+    {
+        std::istream *stream = static_cast<oggStream*>(user_data)->fstream;
+        stream->clear();
+
+        stream->read(static_cast<char*>(ptr), nmemb*size);
+        size_t ret = stream->gcount();
+        return ret/size;
+    }
+
+    static long tell(void *user_data)
+    {
+        std::istream *stream = static_cast<oggStream*>(user_data)->fstream;
+        stream->clear();
+        return stream->tellg();
+    }
+
+    static int close(void*)
+    {
+        return 0;
+    }
+};
+// Priority = 2, so it's preferred over libsndfile and libFLAC
+static DecoderDecl<oggStream,2> oggStream_decoder;
+Decoder &alure_init_vorbisfile(void)
+{ return oggStream_decoder; }
diff --git a/src/codec_wav.cpp b/src/codec_wav.cpp
new file mode 100644 (file)
index 0000000..101e591
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ * ALURE  OpenAL utility library
+ * Copyright (c) 2009-2010 by Chris Robinson.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "config.h"
+
+#include "main.h"
+
+#include <string.h>
+#include <assert.h>
+
+#include <istream>
+
+
+struct wavStream : public alureStream {
+private:
+    ALenum format;
+    int samplerate;
+    int blockAlign;
+    int sampleSize;
+    int channels;
+    long dataStart;
+    long dataLen;
+    size_t remLen;
+
+public:
+    static void Init() { }
+    static void Deinit() { }
+
+    virtual bool IsValid()
+    { return (dataStart > 0 && format != AL_NONE); }
+
+    virtual bool GetFormat(ALenum *fmt, ALuint *frequency, ALuint *blockalign)
+    {
+        *fmt = format;
+        *frequency = samplerate;
+        *blockalign = blockAlign;
+        return true;
+    }
+
+    virtual ALuint GetData(ALubyte *data, ALuint bytes)
+    {
+        std::streamsize rem = ((remLen >= bytes) ? bytes : remLen) / blockAlign;
+        fstream->read(reinterpret_cast<char*>(data), rem*blockAlign);
+
+        std::streamsize got = fstream->gcount();
+        got -= got%blockAlign;
+        remLen -= got;
+
+        if(BigEndian && sampleSize == 16)
+        {
+            for(std::streamsize i = 0;i < got;i+=2)
+                swap(data[i], data[i+1]);
+        }
+        else if(BigEndian && sampleSize == 32)
+        {
+            for(std::streamsize i = 0;i < got;i+=4)
+            {
+                swap(data[i+0], data[i+3]);
+                swap(data[i+1], data[i+2]);
+            }
+        }
+        else if(BigEndian && sampleSize == 64)
+        {
+            for(std::streamsize i = 0;i < got;i+=8)
+            {
+                swap(data[i+0], data[i+7]);
+                swap(data[i+1], data[i+6]);
+                swap(data[i+2], data[i+5]);
+                swap(data[i+3], data[i+4]);
+            }
+        }
+
+        return got;
+    }
+
+    virtual bool Rewind()
+    {
+        fstream->clear();
+        if(fstream->seekg(dataStart))
+        {
+            remLen = dataLen;
+            return true;
+        }
+
+        SetError("Seek failed");
+        return false;
+    }
+
+    virtual alureInt64 GetLength()
+    {
+        alureInt64 ret = dataLen;
+        return ret / channels * 8 / sampleSize;
+    }
+
+    wavStream(std::istream *_fstream)
+      : alureStream(_fstream), format(0), dataStart(0)
+    {
+        ALubyte buffer[25];
+        ALuint length;
+
+        if(!fstream->read(reinterpret_cast<char*>(buffer), 12) ||
+           memcmp(buffer, "RIFF", 4) != 0 || memcmp(buffer+8, "WAVE", 4) != 0)
+            return;
+
+        while(!dataStart || format == AL_NONE)
+        {
+            char tag[4];
+            if(!fstream->read(tag, 4))
+                break;
+
+            /* read chunk length */
+            length = read_le32(fstream);
+
+            if(memcmp(tag, "fmt ", 4) == 0 && length >= 16)
+            {
+                /* Data type (should be 1 for PCM data, 3 for float PCM data,
+                 * 7 for muLaw, and 17 for IMA4 data) */
+                int type = read_le16(fstream);
+                if(type != 0x0001 && type != 0x0003 && type != 0x0007 &&
+                   type != 0x0011)
+                    break;
+
+                /* mono or stereo data */
+                channels = read_le16(fstream);
+
+                /* sample frequency */
+                samplerate = read_le32(fstream);
+
+                /* skip average bytes per second */
+                fstream->ignore(4);
+
+                /* bytes per block */
+                blockAlign = read_le16(fstream);
+                if(blockAlign == 0)
+                    break;
+
+                /* bits per sample */
+                sampleSize = read_le16(fstream);
+
+                length -= 16;
+
+                /* Look for any extra data and try to find the format */
+                ALuint extrabytes = 0;
+                if(length >= 2)
+                {
+                    extrabytes = read_le16(fstream);
+                    length -= 2;
+                }
+                extrabytes = std::min<ALuint>(extrabytes, length);
+
+                if(type == 0x0001)
+                    format = GetSampleFormat(channels, sampleSize, false);
+                else if(type == 0x0003)
+                    format = GetSampleFormat(channels, sampleSize, true);
+                else if(type == 0x0007)
+                {
+                    if(sampleSize == 8)
+                    {
+                        if(channels == 1)
+                            format = AL_FORMAT_MONO_MULAW;
+                        else if(channels == 2)
+                            format = AL_FORMAT_STEREO_MULAW;
+                        else if(channels == 4)
+                            format = AL_FORMAT_QUAD_MULAW;
+                        else if(channels == 6)
+                            format = AL_FORMAT_51CHN_MULAW;
+                        else if(channels == 7)
+                            format = AL_FORMAT_61CHN_MULAW;
+                        else if(channels == 8)
+                            format = AL_FORMAT_71CHN_MULAW;
+                    }
+                }
+                else if(type == 0x0011 && extrabytes >= 2)
+                {
+                    int samples = read_le16(fstream);
+                    length -= 2;
+
+                    /* AL_EXT_IMA4 only supports 36 bytes-per-channel block
+                     * alignment, which has 65 uncompressed sample frames */
+                    if(blockAlign == 36*channels && samples == 65*channels &&
+                       alIsExtensionPresent("AL_EXT_IMA4"))
+                    {
+                         if(channels == 1)
+                             format = AL_FORMAT_MONO_IMA4;
+                         else if(channels == 2)
+                             format = AL_FORMAT_STEREO_IMA4;
+                    }
+                }
+            }
+            else if(memcmp(tag, "data", 4) == 0)
+            {
+                dataStart = fstream->tellg();
+                dataLen = remLen = length;
+            }
+
+            fstream->seekg(length, std::ios_base::cur);
+        }
+
+        if(dataStart > 0 && format != AL_NONE)
+            fstream->seekg(dataStart);
+    }
+
+    virtual ~wavStream()
+    { }
+};
+// Priority = 10, prefer this decoder over external ones
+static DecoderDecl<wavStream,10> wavStream_decoder;
+Decoder &alure_init_wav(void)
+{ return wavStream_decoder; }
diff --git a/src/istream.cpp b/src/istream.cpp
new file mode 100644 (file)
index 0000000..803c4b6
--- /dev/null
@@ -0,0 +1,273 @@
+/*
+ * ALURE  OpenAL utility library
+ * Copyright (c) 2009 by Chris Robinson.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+/* Title: File I/O */
+
+#include "config.h"
+
+#include "main.h"
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <iostream>
+
+
+MemStreamBuf::int_type MemStreamBuf::underflow()
+{
+    if(gptr() == egptr())
+    {
+        char_type *data = (char_type*)memInfo.Data;
+        setg(data, data + memInfo.Pos, data + memInfo.Length);
+        memInfo.Pos = memInfo.Length;
+    }
+    if(gptr() == egptr())
+        return traits_type::eof();
+    return (*gptr())&0xFF;
+}
+
+MemStreamBuf::pos_type MemStreamBuf::seekoff(off_type offset, std::ios_base::seekdir whence, std::ios_base::openmode mode)
+{
+    if((mode&std::ios_base::out))
+        return traits_type::eof();
+
+    pos_type pos;
+    switch(whence)
+    {
+        case std::ios_base::beg:
+            pos = pos_type(offset);
+            break;
+        case std::ios_base::cur:
+            pos = pos_type(memInfo.Pos) - pos_type(egptr()-gptr());
+            pos += offset;
+            break;
+        case std::ios_base::end:
+            pos = memInfo.Length + pos_type(offset);
+            break;
+        default:
+            return traits_type::eof();
+    }
+
+    return seekpos(pos, mode);
+}
+
+MemStreamBuf::pos_type MemStreamBuf::seekpos(pos_type pos, std::ios_base::openmode mode)
+{
+    if((mode&std::ios_base::out))
+        return traits_type::eof();
+
+    if(pos < 0 || pos > pos_type(memInfo.Length) || pos != pos_type(size_t(pos)))
+        return traits_type::eof();
+    memInfo.Pos = pos;
+
+    setg(0, 0, 0);
+    return pos;
+}
+
+
+int FileStreamBuf::underflow()
+{
+    if(usrFile && gptr() == egptr())
+    {
+        ALsizei amt = fio.read(usrFile, reinterpret_cast<ALubyte*>(&buffer[0]), sizeof(buffer));
+        if(amt >= 0) setg(buffer, buffer, buffer+amt);
+    }
+    if(gptr() == egptr())
+        return traits_type::eof();
+    return (*gptr())&0xFF;
+}
+
+FileStreamBuf::pos_type FileStreamBuf::seekoff(off_type offset, std::ios_base::seekdir whence, std::ios_base::openmode mode)
+{
+    if(!usrFile || (mode&std::ios_base::out))
+        return traits_type::eof();
+
+    pos_type pos = traits_type::eof();
+    switch(whence)
+    {
+        case std::ios_base::beg:
+            if(offset == off_type(alureInt64(offset)))
+                pos = pos_type(fio.seek(usrFile, offset, SEEK_SET));
+            break;
+
+        case std::ios_base::cur:
+            offset -= off_type(egptr()-gptr());
+            if(offset == off_type(alureInt64(offset)))
+                pos = pos_type(fio.seek(usrFile, offset, SEEK_CUR));
+            break;
+
+        case std::ios_base::end:
+            if(offset == off_type(alureInt64(offset)))
+                pos = pos_type(fio.seek(usrFile, offset, SEEK_END));
+            break;
+
+        default:
+            break;
+    }
+    if(pos >= 0)
+        setg(0, 0, 0);
+    return pos;
+}
+
+FileStreamBuf::pos_type FileStreamBuf::seekpos(pos_type pos, std::ios_base::openmode mode)
+{
+    if(pos != pos_type(off_type(pos)))
+        return traits_type::eof();
+    return seekoff(off_type(pos), std::ios_base::beg, mode);
+}
+
+
+static void *open_wrap(const char *filename, ALuint mode)
+{
+    if(mode != 0)
+        return NULL;
+
+    return fopen(filename, "rb");
+}
+
+static void close_wrap(void *user_data)
+{
+    FILE *f = (FILE*)user_data;
+    fclose(f);
+}
+
+static ALsizei read_wrap(void *user_data, ALubyte *buf, ALuint bytes)
+{
+    FILE *f = (FILE*)user_data;
+    return fread(buf, 1, bytes, f);
+}
+
+static ALsizei write_wrap(void *user_data, const ALubyte *buf, ALuint bytes)
+{
+    FILE *f = (FILE*)user_data;
+    return fwrite(buf, 1, bytes, f);
+}
+
+static alureInt64 seek_wrap(void *user_data, alureInt64 offset, int whence)
+{
+    FILE *f = (FILE*)user_data;
+#ifdef HAVE_FSEEKO
+    if(offset != (off_t)offset || fseeko(f, offset, whence) != 0)
+        return -1;
+    return ftello(f);
+#elif defined(HAVE__FSEEKI64)
+    if(_fseeki64(f, offset, whence) != 0)
+        return -1;
+    return _ftelli64(f);
+#else
+    if(offset != (long)offset || fseek(f, offset, whence) != 0)
+        return -1;
+    return ftell(f);
+#endif
+}
+
+UserFuncs Funcs = {
+    open_wrap,
+    close_wrap,
+    read_wrap,
+    write_wrap,
+    seek_wrap
+};
+bool UsingSTDIO = true;
+
+extern "C" {
+
+/* Function: alureSetIOCallbacks
+ *
+ * Provides callbacks for alternative methods to handle file I/O. Passing NULL
+ * for all callbacks is a valid way to revert to normal I/O, otherwise they
+ * must all be specified. Changing the callbacks will not affect open files
+ * (they will continue using the callbacks that were set at the time they were
+ * opened).
+ *
+ * Parameters:
+ * open - This callback is called to open the named file. The given mode is the
+ *        access rights the open file should have. Currently, this will always
+ *        be 0 for read-only (applications should check this to make sure, as
+ *        future versions may pass other values for other modes). Upon success,
+ *        a non-NULL handle must be returned which will be used as a unique
+ *        identifier for the file.
+ * close - This callback is called to close an opened file handle. The handle
+ *         will no longer be used after this function.
+ * read - This callback is called when data needs to be read from the given
+ *        handle. Up to the given number of bytes should be copied into 'buf'
+ *        and the number of bytes actually copied should be returned. Returning
+ *        0 means the end of the file has been reached (so non-blocking I/O
+ *        methods should ensure at least 1 byte gets read), and negative
+ *        indicates an error.
+ * write - This callback is called when data needs to be written to the given
+ *         handle. Up to the given number of bytes should be copied from 'buf'
+ *         and the number of bytes actually copied should be returned. A return
+ *         value of 0 means no more data can be written (so non-blocking I/O
+ *         methods should ensure at least 1 byte gets written), and negative
+ *         indicates an error.
+ * seek - This callback is called to reposition the offset of the file handle.
+ *        The given offset is interpreted according to 'whence', which may be
+ *        SEEK_SET (absolute position from the start of the file), SEEK_CUR
+ *        (relative position from the current offset), or SEEK_END (absolute
+ *        position from the end of the file), as defined by standard C. The new
+ *        offset from the beginning of the file should be returned. If the file
+ *        cannot seek, such as when using a FIFO, -1 should be returned.
+ *
+ * Returns:
+ * AL_FALSE on error.
+ *
+ * *Version Added*: 1.1
+ */
+ALURE_API ALboolean ALURE_APIENTRY alureSetIOCallbacks(
+      void* (*open)(const char *filename, ALuint mode),
+      void (*close)(void *handle),
+      ALsizei (*read)(void *handle, ALubyte *buf, ALuint bytes),
+      ALsizei (*write)(void *handle, const ALubyte *buf, ALuint bytes),
+      alureInt64 (*seek)(void *handle, alureInt64 offset, int whence))
+{
+    if(open && close && read && write && seek)
+    {
+        Funcs.open = open;
+        Funcs.close = close;
+        Funcs.read = read;
+        Funcs.write = write;
+        Funcs.seek = seek;
+        UsingSTDIO = false;
+        return AL_TRUE;
+    }
+
+    if(!open && !close && !read && !write && !seek)
+    {
+        Funcs.open = open_wrap;
+        Funcs.close = close_wrap;
+        Funcs.read = read_wrap;
+        Funcs.write = write_wrap;
+        Funcs.seek = seek_wrap;
+        UsingSTDIO = true;
+        return AL_TRUE;
+    }
+
+    SetError("Missing callback functions");
+    return AL_FALSE;
+}
+
+} // extern "C"
diff --git a/src/stream.cpp b/src/stream.cpp
new file mode 100644 (file)
index 0000000..4607489
--- /dev/null
@@ -0,0 +1,607 @@
+/*
+ * ALURE  OpenAL utility library
+ * Copyright (c) 2009 by Chris Robinson.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+/* Title: Streaming */
+
+#include "config.h"
+
+#include "main.h"
+
+#include <string.h>
+
+#include <memory>
+
+static bool SizeIsUS = false;
+
+static alureStream *InitStream(alureStream *instream, ALsizei chunkLength, ALsizei numBufs, ALuint *bufs)
+{
+    std::auto_ptr<std::istream> fstream(instream->fstream);
+    std::auto_ptr<alureStream> stream(instream);
+    ALenum format;
+    ALuint freq, blockAlign;
+
+    if(!stream->GetFormat(&format, &freq, &blockAlign))
+    {
+        SetError("Could not get stream format");
+        return NULL;
+    }
+
+    if(format == AL_NONE || format == -1)
+    {
+        SetError("No valid format");
+        return NULL;
+    }
+    if(blockAlign == 0)
+    {
+        SetError("Invalid block size");
+        return NULL;
+    }
+    if(freq == 0)
+    {
+        SetError("Invalid sample rate");
+        return NULL;
+    }
+
+    if(SizeIsUS)
+    {
+        ALuint framesPerBlock = DetectCompressionRate(format);
+        ALuint blockSize = DetectBlockAlignment(format);
+        if(framesPerBlock == 0 || blockSize == 0)
+        {
+            SetError("Unknown compression rate");
+            return NULL;
+        }
+
+        alureUInt64 len64 = chunkLength;
+        len64 = len64 * freq / 1000000 / framesPerBlock * blockSize;
+        if(len64 > 0x7FFFFFFF)
+        {
+            SetError("Chunk length too large");
+            return NULL;
+        }
+        chunkLength = len64;
+    }
+
+    chunkLength -= chunkLength%blockAlign;
+    if(chunkLength <= 0)
+    {
+        SetError("Chunk length too small");
+        return NULL;
+    }
+
+    stream->dataChunk.resize(chunkLength);
+
+    if(numBufs > 0)
+    {
+        alGenBuffers(numBufs, bufs);
+        if(alGetError() != AL_NO_ERROR)
+        {
+            SetError("Buffer creation failed");
+            return NULL;
+        }
+    }
+
+    ALsizei filled;
+    for(filled = 0;filled < numBufs;filled++)
+    {
+        ALuint got = stream->GetData(&stream->dataChunk[0], stream->dataChunk.size());
+        got -= got%blockAlign;
+        if(got == 0) break;
+
+        alBufferData(bufs[filled], format, &stream->dataChunk[0], got, freq);
+    }
+
+    while(filled < numBufs)
+    {
+        alBufferData(bufs[filled], format, &stream->dataChunk[0], 0, freq);
+        filled++;
+    }
+    if(alGetError() != AL_NO_ERROR)
+    {
+        alDeleteBuffers(numBufs, bufs);
+        alGetError();
+
+        SetError("Buffering error");
+        return NULL;
+    }
+
+    fstream.release();
+    return stream.release();
+}
+
+
+extern "C" {
+
+/* Function: alureStreamSizeIsMicroSec
+ *
+ * Specifies if the chunk size value given to the alureCreateStream functions
+ * is in bytes (default) or microseconds. Specifying the size in microseconds
+ * can help manage the time needed in between needed updates (since the format
+ * and sample rate of the stream may not be known), while specifying the size
+ * in bytes can help control memory usage.
+ *
+ * Returns:
+ * Previously set value.
+ *
+ * *Version Added*: 1.1
+ *
+ * See Also:
+ * <alureCreateStreamFromFile>, <alureCreateStreamFromMemory>,
+ * <alureCreateStreamFromStaticMemory>, <alureCreateStreamFromCallback>
+ */
+ALURE_API ALboolean ALURE_APIENTRY alureStreamSizeIsMicroSec(ALboolean useUS)
+{
+    ALboolean old = (SizeIsUS ? AL_TRUE : AL_FALSE);
+    SizeIsUS = !!useUS;
+    return old;
+}
+
+/* Function: alureCreateStreamFromFile
+ *
+ * Opens a file and sets it up for streaming. The given chunkLength is the
+ * number of bytes, or microseconds worth of bytes if
+ * <alureStreamSizeIsMicroSec> was last called with AL_TRUE, each buffer will
+ * fill with. ALURE will optionally generate the specified number of buffer
+ * objects, fill them with the beginning of the data, then place the new IDs
+ * into the provided storage, before returning. Requires an active context.
+ *
+ * Returns:
+ * An opaque handle used to control the opened stream, or NULL on error.
+ *
+ * See Also:
+ * <alureStreamSizeIsMicroSec>, <alureCreateStreamFromMemory>,
+ * <alureCreateStreamFromStaticMemory>, <alureCreateStreamFromCallback>
+ */
+ALURE_API alureStream* ALURE_APIENTRY alureCreateStreamFromFile(const ALchar *fname, ALsizei chunkLength, ALsizei numBufs, ALuint *bufs)
+{
+    if(alGetError() != AL_NO_ERROR)
+    {
+        SetError("Existing OpenAL error");
+        return NULL;
+    }
+
+    if(chunkLength < 0)
+    {
+        SetError("Invalid chunk length");
+        return NULL;
+    }
+
+    if(numBufs < 0)
+    {
+        SetError("Invalid buffer count");
+        return NULL;
+    }
+
+    alureStream *stream = create_stream(fname);
+    if(!stream) return NULL;
+
+    return InitStream(stream, chunkLength, numBufs, bufs);
+}
+
+/* Function: alureCreateStreamFromMemory
+ *
+ * Opens a file image from memory and sets it up for streaming, similar to
+ * <alureCreateStreamFromFile>. The given data buffer can be safely deleted
+ * after calling this function. Requires an active context.
+ *
+ * Returns:
+ * An opaque handle used to control the opened stream, or NULL on error.
+ *
+ * See Also:
+ * <alureStreamSizeIsMicroSec>, <alureCreateStreamFromFile>,
+ * <alureCreateStreamFromStaticMemory>, <alureCreateStreamFromCallback>
+ */
+ALURE_API alureStream* ALURE_APIENTRY alureCreateStreamFromMemory(const ALubyte *fdata, ALuint length, ALsizei chunkLength, ALsizei numBufs, ALuint *bufs)
+{
+    if(alGetError() != AL_NO_ERROR)
+    {
+        SetError("Existing OpenAL error");
+        return NULL;
+    }
+
+    if(chunkLength < 0)
+    {
+        SetError("Invalid chunk length");
+        return NULL;
+    }
+
+    if(numBufs < 0)
+    {
+        SetError("Invalid buffer count");
+        return NULL;
+    }
+
+    if(length <= 0)
+    {
+        SetError("Invalid data length");
+        return NULL;
+    }
+
+    ALubyte *streamData = new ALubyte[length];
+    memcpy(streamData, fdata, length);
+
+    MemDataInfo memData;
+    memData.Data = streamData;
+    memData.Length = length;
+    memData.Pos = 0;
+
+    alureStream *stream = create_stream(memData);
+    if(!stream) return NULL;
+
+    stream->data = streamData;
+    return InitStream(stream, chunkLength, numBufs, bufs);
+}
+
+/* Function: alureCreateStreamFromStaticMemory
+ *
+ * Identical to <alureCreateStreamFromMemory>, except the given memory is used
+ * directly and not duplicated. As a consequence, the data buffer must remain
+ * valid while the stream is alive. Requires an active context.
+ *
+ * Returns:
+ * An opaque handle used to control the opened stream, or NULL on error.
+ *
+ * See Also:
+ * <alureStreamSizeIsMicroSec>, <alureCreateStreamFromFile>,
+ * <alureCreateStreamFromMemory>, <alureCreateStreamFromCallback>
+ */
+ALURE_API alureStream* ALURE_APIENTRY alureCreateStreamFromStaticMemory(const ALubyte *fdata, ALuint length, ALsizei chunkLength, ALsizei numBufs, ALuint *bufs)
+{
+    if(alGetError() != AL_NO_ERROR)
+    {
+        SetError("Existing OpenAL error");
+        return NULL;
+    }
+
+    if(chunkLength < 0)
+    {
+        SetError("Invalid chunk length");
+        return NULL;
+    }
+
+    if(numBufs < 0)
+    {
+        SetError("Invalid buffer count");
+        return NULL;
+    }
+
+    if(length <= 0)
+    {
+        SetError("Invalid data length");
+        return NULL;
+    }
+
+    MemDataInfo memData;
+    memData.Data = fdata;
+    memData.Length = length;
+    memData.Pos = 0;
+
+    alureStream *stream = create_stream(memData);
+    if(!stream) return NULL;
+
+    return InitStream(stream, chunkLength, numBufs, bufs);
+}
+
+/* Function: alureCreateStreamFromCallback
+ *
+ * Creates a stream using the specified callback to retrieve data. Requires an
+ * active context.
+ *
+ * Parameters:
+ * callback - This is called when more data is needed from the stream. Up to
+ *            the specified number of bytes should be written to the data
+ *            pointer, and the number of bytes actually written should be
+ *            returned. The number of bytes written must be block aligned for
+ *            the format (eg. a multiple of 4 for AL_FORMAT_STEREO16), or an
+ *            OpenAL error may occur during buffering.
+ * userdata - A handle passed through to the callback.
+ * format - The format of the data the callback will be giving. The format must
+ *          be valid for the context.
+ * samplerate - The sample rate (frequency) of the stream
+ *
+ * Returns:
+ * An opaque handle used to control the opened stream, or NULL on error.
+ *
+ * See Also:
+ * <alureStreamSizeIsMicroSec>, <alureCreateStreamFromFile>,
+ * <alureCreateStreamFromMemory>, <alureCreateStreamFromStaticMemory>
+ */
+ALURE_API alureStream* ALURE_APIENTRY alureCreateStreamFromCallback(
+      ALuint (*callback)(void *userdata, ALubyte *data, ALuint bytes),
+      void *userdata, ALenum format, ALuint samplerate,
+      ALsizei chunkLength, ALsizei numBufs, ALuint *bufs)
+{
+    if(alGetError() != AL_NO_ERROR)
+    {
+        SetError("Existing OpenAL error");
+        return NULL;
+    }
+
+    if(callback == NULL)
+    {
+        SetError("Invalid callback");
+        return NULL;
+    }
+
+    if(chunkLength < 0)
+    {
+        SetError("Invalid chunk length");
+        return NULL;
+    }
+
+    if(numBufs < 0)
+    {
+        SetError("Invalid buffer count");
+        return NULL;
+    }
+
+    UserCallbacks newcb;
+    newcb.open_file = NULL;
+    newcb.open_mem  = NULL;
+    newcb.get_fmt   = NULL;
+    newcb.decode    = callback;
+    newcb.rewind    = NULL;
+    newcb.close     = NULL;
+
+    alureStream *stream = create_stream(userdata, format, samplerate, newcb);
+    return InitStream(stream, chunkLength, numBufs, bufs);
+}
+
+/* Function: alureGetStreamFrequency
+ *
+ * Retrieves the frequency used by the given stream.
+ *
+ * Returns:
+ * 0 on error.
+ *
+ * *Version Added*: 1.1
+ */
+ALURE_API ALsizei ALURE_APIENTRY alureGetStreamFrequency(alureStream *stream)
+{
+    ALenum format;
+    ALuint rate, balign;
+
+    if(!alureStream::Verify(stream))
+    {
+        SetError("Invalid stream pointer");
+        return 0;
+    }
+
+    if(!stream->GetFormat(&format, &rate, &balign))
+    {
+        SetError("Could not get stream format");
+        return 0;
+    }
+
+    return rate;
+}
+
+/* Function: alureBufferDataFromStream
+ *
+ * Buffers the given buffer objects with the next chunks of data from the
+ * stream. The given buffer objects do not need to be ones given by the
+ * alureCreateStream functions. Requires an active context.
+ *
+ * Returns:
+ * The number of buffers filled with new data, or -1 on error. If the value
+ * returned is less than the number requested, the end of the stream has been
+ * reached.
+ */
+ALURE_API ALsizei ALURE_APIENTRY alureBufferDataFromStream(alureStream *stream, ALsizei numBufs, ALuint *bufs)
+{
+    if(alGetError() != AL_NO_ERROR)
+    {
+        SetError("Existing OpenAL error");
+        return -1;
+    }
+
+    if(!alureStream::Verify(stream))
+    {
+        SetError("Invalid stream pointer");
+        return -1;
+    }
+
+    if(numBufs < 0)
+    {
+        SetError("Invalid buffer count");
+        return -1;
+    }
+
+    for(ALsizei i = 0;i < numBufs;i++)
+    {
+        if(!bufs[i] || !alIsBuffer(bufs[i]))
+        {
+            SetError("Invalid buffer ID");
+            return -1;
+        }
+    }
+
+    ALenum format;
+    ALuint freq, blockAlign;
+
+    if(!stream->GetFormat(&format, &freq, &blockAlign))
+    {
+        SetError("Could not get stream format");
+        return -1;
+    }
+
+    ALsizei filled;
+    for(filled = 0;filled < numBufs;filled++)
+    {
+        ALuint got = stream->GetData(&stream->dataChunk[0], stream->dataChunk.size());
+        got -= got%blockAlign;
+        if(got == 0) break;
+
+        alBufferData(bufs[filled], format, &stream->dataChunk[0], got, freq);
+        if(alGetError() != AL_NO_ERROR)
+        {
+            SetError("Buffer load failed");
+            return -1;
+        }
+    }
+
+    return filled;
+}
+
+/* Function: alureRewindStream
+ *
+ * Rewinds the stream so that the next alureBufferDataFromStream call will
+ * restart from the beginning of the audio file.
+ *
+ * Returns:
+ * AL_FALSE on error.
+ *
+ * See Also:
+ * <alureSetStreamOrder>
+ */
+ALURE_API ALboolean ALURE_APIENTRY alureRewindStream(alureStream *stream)
+{
+    if(!alureStream::Verify(stream))
+    {
+        SetError("Invalid stream pointer");
+        return AL_FALSE;
+    }
+
+    return stream->Rewind();
+}
+
+/* Function: alureSetStreamOrder
+ *
+ * Skips the module decoder to the specified order, so following buffering
+ * calls will decode from the specified order. For non-module formats, setting
+ * order 0 is identical to rewinding the stream (other orders will fail).
+ *
+ * Returns:
+ * AL_FALSE on error.
+ *
+ * *Version Added*: 1.1
+ *
+ * See Also:
+ * <alureRewindStream>
+ */
+ALURE_API ALboolean ALURE_APIENTRY alureSetStreamOrder(alureStream *stream, ALuint order)
+{
+    if(!alureStream::Verify(stream))
+    {
+        SetError("Invalid stream pointer");
+        return AL_FALSE;
+    }
+
+    return stream->SetOrder(order);
+}
+
+/* Function: alureSetStreamPatchset
+ *
+ * Specifies the patchset to use for MIDI streams. By default, the FluidSynth
+ * decoder will look for one in the FLUID_SOUNDFONT environment variable, but
+ * this can be used to change it to something different. On non-MIDI streams,
+ * this has no effect.
+ *
+ * Returns:
+ * AL_FALSE on error.
+ *
+ * *Version Added*: 1.1
+ */
+ALURE_API ALboolean ALURE_APIENTRY alureSetStreamPatchset(alureStream *stream, const ALchar *patchset)
+{
+    if(!alureStream::Verify(stream))
+    {
+        SetError("Invalid stream pointer");
+        return AL_FALSE;
+    }
+
+    return stream->SetPatchset(patchset);
+}
+
+/* Function: alureGetStreamLength
+ *
+ * Retrieves an approximate number of samples for the stream. Not all streams
+ * or decoders can return such info, and may return 0 if the stream length is
+ * unknown.
+ *
+ * Returns:
+ * -1 on error.
+ *
+ * *Version Added*: 1.2
+ */
+ALURE_API alureInt64 ALURE_APIENTRY alureGetStreamLength(alureStream *stream)
+{
+    if(!alureStream::Verify(stream))
+    {
+        SetError("Invalid stream pointer");
+        return -1;
+    }
+
+    return stream->GetLength();
+}
+
+/* Function: alureDestroyStream
+ *
+ * Closes an opened stream. For convenience, it will also delete the given
+ * buffer objects. The given buffer objects do not need to be ones given by the
+ * alureCreateStream functions. Requires an active context.
+ *
+ * Returns:
+ * AL_FALSE on error.
+ */
+ALURE_API ALboolean ALURE_APIENTRY alureDestroyStream(alureStream *stream, ALsizei numBufs, ALuint *bufs)
+{
+    if(alGetError() != AL_NO_ERROR)
+    {
+        SetError("Existing OpenAL error");
+        return AL_FALSE;
+    }
+
+    if(numBufs < 0)
+    {
+        SetError("Invalid buffer count");
+        return AL_FALSE;
+    }
+
+    if(stream && !alureStream::Verify(stream))
+    {
+        SetError("Invalid stream pointer");
+        return AL_FALSE;
+    }
+
+    if(numBufs > 0)
+    {
+        alDeleteBuffers(numBufs, bufs);
+        if(alGetError() != AL_NO_ERROR)
+        {
+            SetError("Buffer deletion failed");
+            return AL_FALSE;
+        }
+    }
+
+    if(stream)
+    {
+        StopStream(stream);
+        std::istream *f = stream->fstream;
+        delete stream;
+        delete f;
+    }
+    return AL_TRUE;
+}
+
+}
diff --git a/src/streamdec.cpp b/src/streamdec.cpp
new file mode 100644 (file)
index 0000000..add6365
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * ALURE  OpenAL utility library
+ * Copyright (c) 2009-2010 by Chris Robinson.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "config.h"
+
+#include "main.h"
+
+#include <string.h>
+#include <assert.h>
+
+#include <algorithm>
+#include <vector>
+#include <memory>
+#include <string>
+#include <istream>
+#include <fstream>
+#include <iostream>
+#include <sstream>
+
+
+const Decoder::ListType& Decoder::GetList()
+{ return AddList(); }
+
+Decoder::ListType& Decoder::AddList(Decoder::FactoryType func, ALint prio)
+{
+    static ListType FuncList;
+    if(func)
+    {
+        assert(SearchSecond(FuncList.begin(), FuncList.end(), func) == FuncList.end());
+        FuncList.insert(std::make_pair(prio, func));
+    }
+    return FuncList;
+}
+
+
+struct customStream : public alureStream {
+    void *usrFile;
+    ALenum format;
+    ALuint samplerate;
+    ALuint blockAlign;
+    MemDataInfo memInfo;
+
+    UserCallbacks cb;
+
+    virtual bool IsValid()
+    { return usrFile != NULL; }
+
+    virtual bool GetFormat(ALenum *fmt, ALuint *frequency, ALuint *blockalign)
+    {
+        if(format == AL_NONE)
+        {
+            if(!cb.get_fmt || !cb.get_fmt(usrFile, &format, &samplerate, &blockAlign))
+                return false;
+
+            ALuint detected = DetectBlockAlignment(format);
+            if(detected && (blockAlign%detected) != 0)
+                blockAlign = 0;
+        }
+
+        *fmt = format;
+        *frequency = samplerate;
+        *blockalign = blockAlign;
+        return true;
+    }
+
+    virtual ALuint GetData(ALubyte *data, ALuint bytes)
+    { return cb.decode(usrFile, data, bytes); }
+
+    virtual bool Rewind()
+    {
+        if(cb.rewind && cb.rewind(usrFile))
+            return true;
+        SetError("Rewind failed");
+        return false;
+    }
+
+    customStream(const char *fname, const UserCallbacks &callbacks)
+      : alureStream(NULL), usrFile(NULL), format(AL_NONE), samplerate(0),
+        blockAlign(0), cb(callbacks)
+    { if(cb.open_file) usrFile = cb.open_file(fname); }
+
+    customStream(const MemDataInfo &memData, const UserCallbacks &callbacks)
+      : alureStream(NULL), usrFile(NULL), format(AL_NONE), samplerate(0),
+        blockAlign(0), memInfo(memData), cb(callbacks)
+    { if(cb.open_mem) usrFile = cb.open_mem(memInfo.Data, memInfo.Length); }
+
+    customStream(void *userdata, ALenum fmt, ALuint srate, const UserCallbacks &callbacks)
+      : alureStream(NULL), usrFile(userdata), format(fmt), samplerate(srate),
+        blockAlign(DetectBlockAlignment(format)), cb(callbacks)
+    { }
+
+    virtual ~customStream()
+    {
+        if(cb.close && usrFile)
+            cb.close(usrFile);
+        usrFile = NULL;
+    }
+};
+
+
+template <typename T>
+static alureStream *get_stream_decoder(const T &fdata)
+{
+    std::map<ALint,UserCallbacks>::iterator i = InstalledCallbacks.begin();
+    while(i != InstalledCallbacks.end() && i->first < 0)
+    {
+        std::auto_ptr<alureStream> stream(new customStream(fdata, i->second));
+        if(stream->IsValid()) return stream.release();
+        i++;
+    }
+
+    std::istream *file = new InStream(fdata);
+    if(!file->fail())
+    {
+        const Decoder::ListType Factories = Decoder::GetList();
+        Decoder::ListType::const_reverse_iterator factory = Factories.rbegin();
+        Decoder::ListType::const_reverse_iterator end = Factories.rend();
+        while(factory != end)
+        {
+            file->clear();
+            file->seekg(0, std::ios_base::beg);
+
+            std::auto_ptr<alureStream> stream(factory->second(file));
+            if(stream.get() != NULL) return stream.release();
+
+            factory++;
+        }
+
+        SetError("Unsupported type");
+        delete file;
+    }
+    else
+    {
+        SetError("Failed to open file");
+        delete file;
+    }
+
+    while(i != InstalledCallbacks.end())
+    {
+        std::auto_ptr<alureStream> stream(new customStream(fdata, i->second));
+        if(stream->IsValid()) return stream.release();
+        i++;
+    }
+
+    return NULL;
+}
+
+alureStream *create_stream(const char *fname)
+{ return get_stream_decoder(fname); }
+alureStream *create_stream(const MemDataInfo &memData)
+{ return get_stream_decoder(memData); }
+
+alureStream *create_stream(ALvoid *userdata, ALenum format, ALuint rate, const UserCallbacks &cb)
+{ return new customStream(userdata, format, rate, cb); }
diff --git a/src/streamplay.cpp b/src/streamplay.cpp
new file mode 100644 (file)
index 0000000..d33cdb6
--- /dev/null
@@ -0,0 +1,838 @@
+/*
+ * ALURE  OpenAL utility library
+ * Copyright (c) 2009 by Chris Robinson.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+/* Title: Automatic Playback */
+
+#include "config.h"
+
+#include "main.h"
+
+#include <list>
+#include <vector>
+
+#ifdef HAVE_WINDOWS_H
+
+typedef struct {
+    ALuint (*func)(ALvoid*);
+    ALvoid *ptr;
+    HANDLE thread;
+} ThreadInfo;
+
+static DWORD CALLBACK StarterFunc(void *ptr)
+{
+    ThreadInfo *inf = (ThreadInfo*)ptr;
+    ALint ret;
+
+    ret = inf->func(inf->ptr);
+    ExitThread((DWORD)ret);
+
+    return (DWORD)ret;
+}
+
+static ThreadInfo *StartThread(ALuint (*func)(ALvoid*), ALvoid *ptr)
+{
+    DWORD dummy;
+    ThreadInfo *inf = new ThreadInfo;
+    inf->func = func;
+    inf->ptr = ptr;
+
+    inf->thread = CreateThread(NULL, 0, StarterFunc, inf, 0, &dummy);
+    if(!inf->thread)
+    {
+        delete inf;
+        return NULL;
+    }
+
+    return inf;
+}
+
+static ALuint StopThread(ThreadInfo *inf)
+{
+    WaitForSingleObject(inf->thread, INFINITE);
+    CloseHandle(inf->thread);
+    delete inf;
+
+    return 0;
+}
+
+#else
+
+typedef struct {
+    ALuint (*func)(ALvoid*);
+    ALvoid *ptr;
+    pthread_t thread;
+} ThreadInfo;
+
+static void *StarterFunc(void *ptr)
+{
+    ThreadInfo *inf = (ThreadInfo*)ptr;
+    void *ret = (void*)(inf->func(inf->ptr));
+    return ret;
+}
+
+static ThreadInfo *StartThread(ALuint (*func)(ALvoid*), ALvoid *ptr)
+{
+    ThreadInfo *inf = new ThreadInfo;
+    inf->func = func;
+    inf->ptr = ptr;
+
+    if(pthread_create(&inf->thread, NULL, StarterFunc, inf) != 0)
+    {
+        delete inf;
+        return NULL;
+    }
+
+    return inf;
+}
+
+static ALuint StopThread(ThreadInfo *inf)
+{
+    pthread_join(inf->thread, NULL);
+    delete inf;
+
+    return 0;
+}
+
+#endif
+
+// This object is used to make sure the current context isn't switched out on
+// us by another thread, by setting the current thread context to the current
+// context. The old thread context is then restored when the object goes out
+// of scope.
+// This obviously only works when ALC_EXT_thread_local_context is supported
+struct ProtectContext {
+       ProtectContext()
+       { protect(); }
+
+       ~ProtectContext()
+       { unprotect(); }
+
+       void protect()
+       {
+               old_ctx = (alcGetThreadContext ? alcGetThreadContext() : NULL);
+               if(alcSetThreadContext)
+                       alcSetThreadContext(alcGetCurrentContext());
+       }
+
+       void unprotect()
+       {
+               if(alcSetThreadContext)
+               {
+                       if(alcSetThreadContext(old_ctx) == ALC_FALSE)
+                               alcSetThreadContext(NULL);
+               }
+       }
+
+private:
+       ALCcontext *old_ctx;
+};
+#define PROTECT_CONTEXT() ProtectContext _ctx_prot
+#define DO_PROTECT()      _ctx_prot.protect()
+#define DO_UNPROTECT()    _ctx_prot.unprotect()
+
+struct AsyncPlayEntry {
+       ALuint source;
+       alureStream *stream;
+       std::vector<ALuint> buffers;
+       ALsizei loopcount;
+       ALsizei maxloops;
+       void (*eos_callback)(void*,ALuint);
+       void *user_data;
+       bool finished;
+       bool paused;
+       ALuint stream_freq;
+       ALenum stream_format;
+       ALuint stream_align;
+       ALCcontext *ctx;
+
+       AsyncPlayEntry() : source(0), stream(NULL), loopcount(0), maxloops(0),
+                          eos_callback(NULL), user_data(NULL), finished(false),
+                          paused(false), stream_freq(0), stream_format(AL_NONE),
+                          stream_align(0), ctx(NULL)
+       { }
+       AsyncPlayEntry(const AsyncPlayEntry &rhs)
+         : source(rhs.source), stream(rhs.stream), buffers(rhs.buffers),
+           loopcount(rhs.loopcount), maxloops(rhs.maxloops),
+           eos_callback(rhs.eos_callback), user_data(rhs.user_data),
+           finished(rhs.finished), paused(rhs.paused),
+           stream_freq(rhs.stream_freq), stream_format(rhs.stream_format),
+           stream_align(rhs.stream_align), ctx(rhs.ctx)
+       { }
+
+       ALenum Update(ALint *queued)
+       {
+               ALint processed, state;
+
+               alGetSourcei(source, AL_SOURCE_STATE, &state);
+               alGetSourcei(source, AL_BUFFERS_PROCESSED, &processed);
+               while(processed > 0)
+               {
+                       ALuint buf;
+
+                       alSourceUnqueueBuffers(source, 1, &buf);
+                       processed--;
+
+                       while(!finished)
+                       {
+                               ALuint got = stream->GetData(&stream->dataChunk[0], stream->dataChunk.size());
+                               got -= got%stream_align;
+                               if(got > 0)
+                               {
+                                       alBufferData(buf, stream_format, &stream->dataChunk[0], got, stream_freq);
+                                       alSourceQueueBuffers(source, 1, &buf);
+
+                                       break;
+                               }
+                               if(loopcount == maxloops)
+                               {
+                                       finished = true;
+                                       break;
+                               }
+                               if(maxloops != -1)
+                                       loopcount++;
+                               finished = !stream->Rewind();
+                       }
+               }
+
+               alGetSourcei(source, AL_BUFFERS_QUEUED, queued);
+               return state;
+       }
+};
+static std::list<AsyncPlayEntry> AsyncPlayList;
+static ThreadInfo *PlayThreadHandle;
+
+ALfloat CurrentInterval = 0.0f;
+
+ALuint AsyncPlayFunc(ALvoid*)
+{
+       EnterCriticalSection(&cs_StreamPlay);
+       while(CurrentInterval > 0.0f)
+       {
+               alureUpdate();
+
+               ALfloat interval = CurrentInterval;
+               LeaveCriticalSection(&cs_StreamPlay);
+               alureSleep(interval);
+               EnterCriticalSection(&cs_StreamPlay);
+       }
+       LeaveCriticalSection(&cs_StreamPlay);
+       return 0;
+}
+
+
+void StopStream(alureStream *stream)
+{
+       EnterCriticalSection(&cs_StreamPlay);
+
+       std::list<AsyncPlayEntry>::iterator i = AsyncPlayList.begin(),
+                                           end = AsyncPlayList.end();
+       while(i != end)
+       {
+               if(i->stream == stream)
+               {
+                       AsyncPlayEntry ent(*i);
+                       AsyncPlayList.erase(i);
+
+                       ALCcontext *old_ctx = (alcGetThreadContext ?
+                                              alcGetThreadContext() : NULL);
+                       if(alcSetThreadContext)
+                       {
+                               if(alcSetThreadContext(ent.ctx) == ALC_FALSE)
+                                       goto ctx_err;
+                       }
+
+                       alSourceStop(ent.source);
+                       alSourcei(ent.source, AL_BUFFER, 0);
+                       alDeleteBuffers(ent.buffers.size(), &ent.buffers[0]);
+                       alGetError();
+
+                       if(alcSetThreadContext)
+                       {
+                               if(alcSetThreadContext(old_ctx) == ALC_FALSE)
+                                       alcSetThreadContext(NULL);
+                       }
+
+               ctx_err:
+                       if(ent.eos_callback)
+                               ent.eos_callback(ent.user_data, ent.source);
+                       break;
+               }
+               i++;
+       }
+
+       LeaveCriticalSection(&cs_StreamPlay);
+}
+
+
+extern "C" {
+
+/* Function: alurePlaySourceStream
+ *
+ * Starts playing a stream, using the specified source ID. A stream can only be
+ * played if it is not already playing. You must call <alureUpdate> at regular
+ * intervals to keep the stream playing, or else the stream will underrun and
+ * cause a break in the playback until an update call can restart it. It is
+ * also important that the current context is kept for <alureUpdate> calls if
+ * ALC_EXT_thread_local_context is not supported, otherwise the method may
+ * start calling OpenAL with invalid IDs. Note that checking the state of the
+ * specified source is not a good method to determine if a stream is playing.
+ * If an underrun occurs, the source will enter a stopped state until it is
+ * automatically restarted. Instead, set a flag using the callback to indicate
+ * the stream being stopped.
+ *
+ * Parameters:
+ * source - The source ID to play the stream with. Any buffers on the source
+ *          will be unqueued. It is valid to set source properties not related
+ *          to the buffer queue or playback state (ie. you may change the
+ *          source's position, pitch, gain, etc, but you must not stop the
+ *          source or queue/unqueue buffers on it). To pause the source, call
+ *          <alurePauseSource>.
+ * stream - The stream to play. Any valid stream will work, although looping
+ *          will only work if the stream can be rewound (eg. streams made with
+ *          <alureCreateStreamFromCallback> cannot loop, but will play for as
+ *          long as the callback provides data).
+ * numBufs - The number of buffers used to queue with the OpenAL source. Each
+ *           buffer will be filled with the chunk length specified when the
+ *           stream was created. This value must be at least 2. More buffers at
+ *           a larger size will increase the time needed between updates, but
+ *           at the cost of more memory usage.
+ * loopcount - The number of times to loop the stream. When the stream reaches
+ *             the end of processing, it will be rewound to continue buffering
+ *             data. A value of -1 will cause the stream to loop indefinitely
+ *             (or until <alureStopSource> is called).
+ * eos_callback - This callback will be called when the stream reaches the end,
+ *                no more loops are pending, and the source reaches a stopped
+ *                state. It will also be called if an error occured and
+ *                playback terminated.
+ * userdata - An opaque user pointer passed to the callback.
+ *
+ * Returns:
+ * AL_FALSE on error.
+ *
+ * *Version Added*: 1.1
+ *
+ * See Also:
+ * <alureStopSource>, <alurePauseSource>, <alureUpdate>
+ */
+ALURE_API ALboolean ALURE_APIENTRY alurePlaySourceStream(ALuint source,
+    alureStream *stream, ALsizei numBufs, ALsizei loopcount,
+    void (*eos_callback)(void *userdata, ALuint source), void *userdata)
+{
+       PROTECT_CONTEXT();
+       ALCcontext *current_ctx = alcGetCurrentContext();
+
+       if(alGetError() != AL_NO_ERROR)
+       {
+               SetError("Existing OpenAL error");
+               return AL_FALSE;
+       }
+
+       if(!alureStream::Verify(stream))
+       {
+               SetError("Invalid stream pointer");
+               return AL_FALSE;
+       }
+
+       if(numBufs < 2)
+       {
+               SetError("Invalid buffer count");
+               return AL_FALSE;
+       }
+
+       if(!alIsSource(source))
+       {
+               SetError("Invalid source ID");
+               return AL_FALSE;
+       }
+
+       EnterCriticalSection(&cs_StreamPlay);
+
+       std::list<AsyncPlayEntry>::iterator i = AsyncPlayList.begin(),
+                                           end = AsyncPlayList.end();
+       while(i != end)
+       {
+               if(i->stream == stream)
+               {
+                       SetError("Stream is already playing");
+                       LeaveCriticalSection(&cs_StreamPlay);
+                       return AL_FALSE;
+               }
+               if(i->source == source && i->ctx == current_ctx)
+               {
+                       SetError("Source is already playing");
+                       LeaveCriticalSection(&cs_StreamPlay);
+                       return AL_FALSE;
+               }
+               i++;
+       }
+
+       AsyncPlayEntry ent;
+       ent.stream = stream;
+       ent.source = source;
+       ent.maxloops = loopcount;
+       ent.eos_callback = eos_callback;
+       ent.user_data = userdata;
+       ent.ctx = current_ctx;
+
+       ent.buffers.resize(numBufs);
+       alGenBuffers(ent.buffers.size(), &ent.buffers[0]);
+       if(alGetError() != AL_NO_ERROR)
+       {
+               LeaveCriticalSection(&cs_StreamPlay);
+               SetError("Error generating buffers");
+               return AL_FALSE;
+       }
+
+       numBufs = 0;
+       if(ent.stream->GetFormat(&ent.stream_format, &ent.stream_freq, &ent.stream_align))
+       {
+               for(size_t i = 0;i < ent.buffers.size();i++)
+               {
+                       ALuint got = ent.stream->GetData(&ent.stream->dataChunk[0],
+                                                        ent.stream->dataChunk.size());
+                       got -= got%ent.stream_align;
+                       if(got <= 0)
+                       {
+                               if(ent.loopcount == ent.maxloops || i == 0)
+                                       ent.finished = true;
+                               else
+                               {
+                                       if(ent.maxloops != -1)
+                                               ent.loopcount++;
+                                       ent.finished = !ent.stream->Rewind();
+                               }
+                               if(ent.finished)
+                                       break;
+                               i--;
+                               continue;
+                       }
+                       ALuint buf = ent.buffers[i];
+                       alBufferData(buf, ent.stream_format, &ent.stream->dataChunk[0], got, ent.stream_freq);
+                       numBufs++;
+               }
+       }
+       if(numBufs == 0)
+       {
+               alDeleteBuffers(ent.buffers.size(), &ent.buffers[0]);
+               alGetError();
+               LeaveCriticalSection(&cs_StreamPlay);
+               SetError("Error buffering from stream");
+               return AL_FALSE;
+       }
+
+       if((alSourcei(source, AL_LOOPING, AL_FALSE),
+           alSourcei(source, AL_BUFFER, 0),alGetError()) != AL_NO_ERROR ||
+          (alSourceQueueBuffers(source, numBufs, &ent.buffers[0]),
+           alSourcePlay(source),alGetError()) != AL_NO_ERROR)
+       {
+               alSourcei(source, AL_BUFFER, 0);
+               alDeleteBuffers(ent.buffers.size(), &ent.buffers[0]);
+               alGetError();
+               LeaveCriticalSection(&cs_StreamPlay);
+               SetError("Error starting source");
+               return AL_FALSE;
+       }
+
+       AsyncPlayList.push_front(ent);
+
+       LeaveCriticalSection(&cs_StreamPlay);
+
+       return AL_TRUE;
+}
+
+/* Function: alurePlaySource
+ *
+ * Plays the specified source ID and watches for it to stop. When the source
+ * enters an AL_STOPPED or AL_INITIAL state, the specified callback will be
+ * called by <alureUpdate> to alert the application. If
+ * ALC_EXT_thread_local_context is not supported, the current context must not
+ * be changed while the source is being watched (before the callback is called
+ * or <alureStopSource> is called). It also must not be deleted while being
+ * watched.
+ *
+ * Parameters:
+ * source - The source ID to play. As with <alurePlaySourceStream>, it is valid
+ *          to set source properties not related to the playback state (ie. you
+ *          may change a source's position, pitch, gain, etc). Pausing a source
+ *          and restarting a paused source is allowed, and the callback will
+ *          still be called when the source reaches an AL_STOPPED or AL_INITIAL
+ *          state.
+ * callback - The callback to be called when the source stops.
+ * userdata - An opaque user pointer passed to the callback.
+ *
+ * Returns:
+ * AL_FALSE on error.
+ *
+ * *Version Added*: 1.1
+ *
+ * See Also:
+ * <alureStopSource>, <alureUpdate>
+ */
+ALURE_API ALboolean ALURE_APIENTRY alurePlaySource(ALuint source,
+    void (*callback)(void *userdata, ALuint source), void *userdata)
+{
+       PROTECT_CONTEXT();
+       ALCcontext *current_ctx = alcGetCurrentContext();
+
+       if(alGetError() != AL_NO_ERROR)
+       {
+               SetError("Existing OpenAL error");
+               return AL_FALSE;
+       }
+
+       EnterCriticalSection(&cs_StreamPlay);
+
+       std::list<AsyncPlayEntry>::iterator i = AsyncPlayList.begin(),
+                                           end = AsyncPlayList.end();
+       while(i != end)
+       {
+               if(i->source == source && i->ctx == current_ctx)
+               {
+                       SetError("Source is already playing");
+                       LeaveCriticalSection(&cs_StreamPlay);
+                       return AL_FALSE;
+               }
+               i++;
+       }
+
+       if((alSourcePlay(source),alGetError()) != AL_NO_ERROR)
+       {
+               LeaveCriticalSection(&cs_StreamPlay);
+               SetError("Error starting source");
+               return AL_FALSE;
+       }
+
+       if(callback != NULL)
+       {
+               AsyncPlayEntry ent;
+               ent.source = source;
+               ent.eos_callback = callback;
+               ent.user_data = userdata;
+               ent.ctx = current_ctx;
+               AsyncPlayList.push_front(ent);
+       }
+
+       LeaveCriticalSection(&cs_StreamPlay);
+
+       return AL_TRUE;
+}
+
+/* Function: alureStopSource
+ *
+ * Stops the specified source ID, and any associated stream. The previously
+ * specified callback will be invoked if 'run_callback' is not AL_FALSE.
+ * Sources that were not started with <alurePlaySourceStream> or
+ * <alurePlaySource> will still be stopped, but will not have any callback
+ * called for them.
+ *
+ * Returns:
+ * AL_FALSE on error.
+ *
+ * *Version Added*: 1.1
+ *
+ * See Also:
+ * <alurePlaySourceStream>, <alurePlaySource>
+ */
+ALURE_API ALboolean ALURE_APIENTRY alureStopSource(ALuint source, ALboolean run_callback)
+{
+       PROTECT_CONTEXT();
+       ALCcontext *current_ctx = alcGetCurrentContext();
+
+       if(alGetError() != AL_NO_ERROR)
+       {
+               SetError("Existing OpenAL error");
+               return AL_FALSE;
+       }
+
+       EnterCriticalSection(&cs_StreamPlay);
+
+       if((alSourceStop(source),alGetError()) != AL_NO_ERROR)
+       {
+               LeaveCriticalSection(&cs_StreamPlay);
+               SetError("Error stopping source");
+               return AL_FALSE;
+       }
+
+       std::list<AsyncPlayEntry>::iterator i = AsyncPlayList.begin(),
+                                           end = AsyncPlayList.end();
+       while(i != end)
+       {
+               if(i->source == source && i->ctx == current_ctx)
+               {
+                       AsyncPlayEntry ent(*i);
+                       AsyncPlayList.erase(i);
+
+                       if(ent.buffers.size() > 0)
+                       {
+                               alSourcei(ent.source, AL_BUFFER, 0);
+                               alDeleteBuffers(ent.buffers.size(), &ent.buffers[0]);
+                               alGetError();
+                       }
+
+                       if(run_callback && ent.eos_callback)
+                       {
+                               DO_UNPROTECT();
+                               ent.eos_callback(ent.user_data, ent.source);
+                               DO_PROTECT();
+                       }
+                       break;
+               }
+               i++;
+       }
+
+       LeaveCriticalSection(&cs_StreamPlay);
+
+       return AL_TRUE;
+}
+
+/* Function: alurePauseSource
+ *
+ * Pauses the specified source ID, and any associated stream. This is needed to
+ * avoid potential race conditions with sources that are playing a stream.
+ *
+ * Note that it is possible for the specified source to become stopped, and any
+ * associated stream to finish, before this function is called, causing the
+ * callback to be delayed until after the function returns and <alureUpdate>
+ * detects the stopped source.
+ *
+ * Returns:
+ * AL_FALSE on error.
+ *
+ * *Version Added*: 1.1
+ *
+ * See Also:
+ * <alureResumeSource>, <alurePlaySourceStream>, <alurePlaySource>
+ */
+ALURE_API ALboolean ALURE_APIENTRY alurePauseSource(ALuint source)
+{
+       PROTECT_CONTEXT();
+       ALCcontext *current_ctx = alcGetCurrentContext();
+
+       if(alGetError() != AL_NO_ERROR)
+       {
+               SetError("Existing OpenAL error");
+               return AL_FALSE;
+       }
+
+       EnterCriticalSection(&cs_StreamPlay);
+
+       if((alSourcePause(source),alGetError()) != AL_NO_ERROR)
+       {
+               SetError("Error pausing source");
+               LeaveCriticalSection(&cs_StreamPlay);
+               return AL_FALSE;
+       }
+
+       std::list<AsyncPlayEntry>::iterator i = AsyncPlayList.begin(),
+                                           end = AsyncPlayList.end();
+       while(i != end)
+       {
+               if(i->source == source && i->ctx == current_ctx)
+               {
+                       i->paused = true;
+                       break;
+               }
+               i++;
+       }
+
+       LeaveCriticalSection(&cs_StreamPlay);
+
+       return AL_TRUE;
+}
+
+/* Function: alureResumeSource
+ *
+ * Resumes the specified source ID after being paused.
+ *
+ * Returns:
+ * AL_FALSE on error.
+ *
+ * *Version Added*: 1.1
+ *
+ * See Also:
+ * <alurePauseSource>
+ */
+ALURE_API ALboolean ALURE_APIENTRY alureResumeSource(ALuint source)
+{
+       PROTECT_CONTEXT();
+       ALCcontext *current_ctx = alcGetCurrentContext();
+
+       if(alGetError() != AL_NO_ERROR)
+       {
+               SetError("Existing OpenAL error");
+               return AL_FALSE;
+       }
+
+       EnterCriticalSection(&cs_StreamPlay);
+
+       if((alSourcePlay(source),alGetError()) != AL_NO_ERROR)
+       {
+               SetError("Error playing source");
+               LeaveCriticalSection(&cs_StreamPlay);
+               return AL_FALSE;
+       }
+
+       std::list<AsyncPlayEntry>::iterator i = AsyncPlayList.begin(),
+                                           end = AsyncPlayList.end();
+       while(i != end)
+       {
+               if(i->source == source && i->ctx == current_ctx)
+               {
+                       i->paused = false;
+                       break;
+               }
+               i++;
+       }
+
+       LeaveCriticalSection(&cs_StreamPlay);
+
+       return AL_TRUE;
+}
+
+/* Function: alureUpdate
+ *
+ * Updates the running list of streams, and checks for stopped sources. This
+ * makes sure that sources played with <alurePlaySourceStream> are kept fed
+ * from their associated stream, and sources played with <alurePlaySource> are
+ * still playing. It will call their callbacks as needed.
+ *
+ * *Version Added*: 1.1
+ *
+ * See Also:
+ * <alurePlaySourceStream>, <alurePlaySource>
+ */
+ALURE_API void ALURE_APIENTRY alureUpdate(void)
+{
+       PROTECT_CONTEXT();
+
+       EnterCriticalSection(&cs_StreamPlay);
+restart:
+       std::list<AsyncPlayEntry>::iterator i = AsyncPlayList.begin(),
+                                           end = AsyncPlayList.end();
+       for(;i != end;i++)
+       {
+               if(alcSetThreadContext)
+               {
+                       if(alcSetThreadContext(i->ctx) == ALC_FALSE)
+                       {
+                               AsyncPlayEntry ent(*i);
+                               AsyncPlayList.erase(i);
+                               if(ent.eos_callback)
+                               {
+                                       DO_UNPROTECT();
+                                       ent.eos_callback(ent.user_data, ent.source);
+                                       DO_PROTECT();
+                               }
+                               goto restart;
+                       }
+               }
+
+               if(i->stream == NULL)
+               {
+                       ALint state;
+                       alGetSourcei(i->source, AL_SOURCE_STATE, &state);
+                       if(state == AL_STOPPED || state == AL_INITIAL)
+                       {
+                               AsyncPlayEntry ent(*i);
+                               AsyncPlayList.erase(i);
+                               DO_UNPROTECT();
+                               ent.eos_callback(ent.user_data, ent.source);
+                               DO_PROTECT();
+                               goto restart;
+                       }
+                       continue;
+               }
+
+               ALint queued;
+               if(i->Update(&queued) != AL_PLAYING)
+               {
+                       if(queued == 0)
+                       {
+                               AsyncPlayEntry ent(*i);
+                               AsyncPlayList.erase(i);
+
+                               alSourcei(ent.source, AL_BUFFER, 0);
+                               alDeleteBuffers(ent.buffers.size(), &ent.buffers[0]);
+                               if(ent.eos_callback)
+                               {
+                                       DO_UNPROTECT();
+                                       ent.eos_callback(ent.user_data, ent.source);
+                                       DO_PROTECT();
+                               }
+                               goto restart;
+                       }
+                       if(!i->paused)
+                               alSourcePlay(i->source);
+               }
+       }
+       LeaveCriticalSection(&cs_StreamPlay);
+}
+
+/* Function: alureUpdateInterval
+ *
+ * Sets up a timer or thread to automatically call <alureUpdate> at the given
+ * interval, in seconds. If the timer or thread is already running, the update
+ * interval will be modified. A 0 or negative interval will stop <alureUpdate>
+ * from being called.
+ *
+ * Returns:
+ * AL_FALSE on error.
+ *
+ * *Version Added*: 1.1
+ *
+ * See Also:
+ * <alureUpdate>
+ */
+ALURE_API ALboolean ALURE_APIENTRY alureUpdateInterval(ALfloat interval)
+{
+       EnterCriticalSection(&cs_StreamPlay);
+       if(interval <= 0.0f)
+       {
+               CurrentInterval = 0.0f;
+               if(PlayThreadHandle)
+               {
+                       ThreadInfo *threadinf = PlayThreadHandle;
+                       PlayThreadHandle = NULL;
+                       LeaveCriticalSection(&cs_StreamPlay);
+                       StopThread(threadinf);
+                       EnterCriticalSection(&cs_StreamPlay);
+               }
+       }
+       else if(interval > 0.0f)
+       {
+               if(!PlayThreadHandle)
+                       PlayThreadHandle = StartThread(AsyncPlayFunc, NULL);
+               if(!PlayThreadHandle)
+               {
+                       SetError("Error starting async thread");
+                       LeaveCriticalSection(&cs_StreamPlay);
+                       return AL_FALSE;
+               }
+               CurrentInterval = interval;
+       }
+       LeaveCriticalSection(&cs_StreamPlay);
+
+       return AL_TRUE;
+}
+
+} // extern "C"