├── .gitignore ├── .travis.yml ├── ALUT.cabal ├── CHANGELOG.md ├── LICENSE ├── README.md ├── Setup.hs ├── examples ├── Basic │ ├── HelloWorld.hs │ ├── OpenALInfo.hs │ └── PlayFile.hs └── TestSuite │ ├── TestErrorStuff.hs │ ├── TestFileLoader.hs │ ├── TestMemoryLoader.hs │ ├── TestVersion.hs │ ├── TestWaveforms.hs │ ├── file1.wav │ ├── file2.au │ └── file3.raw └── src └── Sound ├── ALUT.hs └── ALUT ├── Config.hs ├── Constants.hs ├── Errors.hs ├── Initialization.hs ├── Loaders.hs ├── Sleep.hs └── Version.hs /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | *~ 3 | /.cabal-sandbox 4 | /dist 5 | /examples/**/*.exe 6 | /examples/**/*.hi 7 | /examples/**/*.o 8 | /examples/Basic/HelloWorld 9 | /examples/Basic/OpenALInfo 10 | /examples/Basic/PlayFile 11 | /examples/TestSuite/TestErrorStuff 12 | /examples/TestSuite/TestFileLoader 13 | /examples/TestSuite/TestMemoryLoader 14 | /examples/TestSuite/TestVersion 15 | /examples/TestSuite/TestWaveforms 16 | cabal.sandbox.config 17 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # This Travis job script has been generated by a script via 2 | # 3 | # haskell-ci 'ALUT.cabal' '--output' '.travis.yml' '--apt' 'libopenal-dev' '--apt' 'libalut-dev' '--apt' 'freeglut3-dev' 4 | # 5 | # For more information, see https://github.com/haskell-CI/haskell-ci 6 | # 7 | # version: 0.3.20190429 8 | # 9 | language: c 10 | dist: xenial 11 | git: 12 | # whether to recursively clone submodules 13 | submodules: false 14 | cache: 15 | directories: 16 | - $HOME/.cabal/packages 17 | - $HOME/.cabal/store 18 | before_cache: 19 | - rm -fv $CABALHOME/packages/hackage.haskell.org/build-reports.log 20 | # remove files that are regenerated by 'cabal update' 21 | - rm -fv $CABALHOME/packages/hackage.haskell.org/00-index.* 22 | - rm -fv $CABALHOME/packages/hackage.haskell.org/*.json 23 | - rm -fv $CABALHOME/packages/hackage.haskell.org/01-index.cache 24 | - rm -fv $CABALHOME/packages/hackage.haskell.org/01-index.tar 25 | - rm -fv $CABALHOME/packages/hackage.haskell.org/01-index.tar.idx 26 | - rm -rfv $CABALHOME/packages/head.hackage 27 | matrix: 28 | include: 29 | - compiler: ghc-8.8.1 30 | addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.8.1","cabal-install-3.0","freeglut3-dev","libalut-dev","libopenal-dev"]}} 31 | env: GHCHEAD=true 32 | - compiler: ghc-8.6.5 33 | addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.6.5","cabal-install-2.4","freeglut3-dev","libalut-dev","libopenal-dev"]}} 34 | - compiler: ghc-8.4.3 35 | addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.4.3","cabal-install-2.4","freeglut3-dev","libalut-dev","libopenal-dev"]}} 36 | - compiler: ghc-8.2.2 37 | addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.2.2","cabal-install-2.4","freeglut3-dev","libalut-dev","libopenal-dev"]}} 38 | - compiler: ghc-8.0.2 39 | addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.0.2","cabal-install-2.4","freeglut3-dev","libalut-dev","libopenal-dev"]}} 40 | - compiler: ghc-7.10.3 41 | addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-7.10.3","cabal-install-2.4","freeglut3-dev","libalut-dev","libopenal-dev"]}} 42 | - compiler: ghc-7.8.4 43 | addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-7.8.4","cabal-install-2.4","freeglut3-dev","libalut-dev","libopenal-dev"]}} 44 | - compiler: ghc-7.6.3 45 | addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-7.6.3","cabal-install-2.4","freeglut3-dev","libalut-dev","libopenal-dev"]}} 46 | - compiler: ghc-7.4.2 47 | addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-7.4.2","cabal-install-2.4","freeglut3-dev","libalut-dev","libopenal-dev"]}} 48 | - compiler: ghc-7.2.2 49 | addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-7.2.2","cabal-install-2.4","freeglut3-dev","libalut-dev","libopenal-dev"]}} 50 | - compiler: ghc-7.0.4 51 | addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-7.0.4","cabal-install-2.4","freeglut3-dev","libalut-dev","libopenal-dev"]}} 52 | allow_failures: 53 | - compiler: ghc-8.8.1 54 | before_install: 55 | - HC=$(echo "/opt/$CC/bin/ghc" | sed 's/-/\//') 56 | - HCPKG="$HC-pkg" 57 | - unset CC 58 | - CABAL=/opt/ghc/bin/cabal 59 | - CABALHOME=$HOME/.cabal 60 | - export PATH="$CABALHOME/bin:$PATH" 61 | - TOP=$(pwd) 62 | - HCNUMVER=$(( $(${HC} --numeric-version|sed -E 's/([0-9]+)\.([0-9]+)\.([0-9]+).*/\1 * 10000 + \2 * 100 + \3/') )) 63 | - echo $HCNUMVER 64 | - CABAL="$CABAL -vnormal+nowrap+markoutput" 65 | - set -o pipefail 66 | - | 67 | echo 'function blue(s) { printf "\033[0;34m" s "\033[0m " }' >> .colorful.awk 68 | echo 'BEGIN { state = "output"; }' >> .colorful.awk 69 | echo '/^-----BEGIN CABAL OUTPUT-----$/ { state = "cabal" }' >> .colorful.awk 70 | echo '/^-----END CABAL OUTPUT-----$/ { state = "output" }' >> .colorful.awk 71 | echo '!/^(-----BEGIN CABAL OUTPUT-----|-----END CABAL OUTPUT-----)/ {' >> .colorful.awk 72 | echo ' if (state == "cabal") {' >> .colorful.awk 73 | echo ' print blue($0)' >> .colorful.awk 74 | echo ' } else {' >> .colorful.awk 75 | echo ' print $0' >> .colorful.awk 76 | echo ' }' >> .colorful.awk 77 | echo '}' >> .colorful.awk 78 | - cat .colorful.awk 79 | - | 80 | color_cabal_output () { 81 | awk -f $TOP/.colorful.awk 82 | } 83 | - echo text | color_cabal_output 84 | install: 85 | - ${CABAL} --version 86 | - echo "$(${HC} --version) [$(${HC} --print-project-git-commit-id 2> /dev/null || echo '?')]" 87 | - TEST=--enable-tests 88 | - BENCH=--enable-benchmarks 89 | - GHCHEAD=${GHCHEAD-false} 90 | - rm -f $CABALHOME/config 91 | - | 92 | echo "verbose: normal +nowrap +markoutput" >> $CABALHOME/config 93 | echo "remote-build-reporting: anonymous" >> $CABALHOME/config 94 | echo "remote-repo-cache: $CABALHOME/packages" >> $CABALHOME/config 95 | echo "logs-dir: $CABALHOME/logs" >> $CABALHOME/config 96 | echo "world-file: $CABALHOME/world" >> $CABALHOME/config 97 | echo "extra-prog-path: $CABALHOME/bin" >> $CABALHOME/config 98 | echo "symlink-bindir: $CABALHOME/bin" >> $CABALHOME/config 99 | echo "installdir: $CABALHOME/bin" >> $CABALHOME/config 100 | echo "build-summary: $CABALHOME/logs/build.log" >> $CABALHOME/config 101 | echo "store-dir: $CABALHOME/store" >> $CABALHOME/config 102 | echo "install-dirs user" >> $CABALHOME/config 103 | echo " prefix: $CABALHOME" >> $CABALHOME/config 104 | echo "repository hackage.haskell.org" >> $CABALHOME/config 105 | echo " url: http://hackage.haskell.org/" >> $CABALHOME/config 106 | - | 107 | if $GHCHEAD; then 108 | echo "allow-newer: $($HCPKG list --simple-output | sed -E 's/([a-zA-Z-]+)-[0-9.]+/*:\1/g')" >> $CABALHOME/config 109 | 110 | echo "repository head.hackage" >> $CABALHOME/config 111 | echo " url: http://head.hackage.haskell.org/" >> $CABALHOME/config 112 | echo " secure: True" >> $CABALHOME/config 113 | echo " root-keys: 07c59cb65787dedfaef5bd5f987ceb5f7e5ebf88b904bbd4c5cbdeb2ff71b740" >> $CABALHOME/config 114 | echo " 2e8555dde16ebd8df076f1a8ef13b8f14c66bad8eafefd7d9e37d0ed711821fb" >> $CABALHOME/config 115 | echo " 8f79fd2389ab2967354407ec852cbe73f2e8635793ac446d09461ffb99527f6e" >> $CABALHOME/config 116 | echo " key-threshold: 3" >> $CABALHOME/config 117 | fi 118 | - cat $CABALHOME/config 119 | - rm -fv cabal.project cabal.project.local cabal.project.freeze 120 | - travis_retry ${CABAL} v2-update -v 121 | # Generate cabal.project 122 | - rm -rf cabal.project cabal.project.local cabal.project.freeze 123 | - touch cabal.project 124 | - | 125 | echo 'packages: "."' >> cabal.project 126 | - | 127 | echo "write-ghc-environment-files: always" >> cabal.project 128 | - "for pkg in $($HCPKG list --simple-output); do echo $pkg | sed 's/-[^-]*$//' | (grep -vE -- '^(ALUT)$' || true) | sed 's/^/constraints: /' | sed 's/$/ installed/' >> cabal.project.local; done" 129 | - cat cabal.project || true 130 | - cat cabal.project.local || true 131 | - if [ -f "./configure.ac" ]; then (cd "." && autoreconf -i); fi 132 | - ${CABAL} v2-freeze -w ${HC} ${TEST} ${BENCH} | color_cabal_output 133 | - "cat cabal.project.freeze | sed -E 's/^(constraints: *| *)//' | sed 's/any.//'" 134 | - rm cabal.project.freeze 135 | - ${CABAL} v2-build -w ${HC} ${TEST} ${BENCH} --dep -j2 all | color_cabal_output 136 | - ${CABAL} v2-build -w ${HC} --disable-tests --disable-benchmarks --dep -j2 all | color_cabal_output 137 | script: 138 | - DISTDIR=$(mktemp -d /tmp/dist-test.XXXX) 139 | # Packaging... 140 | - ${CABAL} v2-sdist all | color_cabal_output 141 | # Unpacking... 142 | - mv dist-newstyle/sdist/*.tar.gz ${DISTDIR}/ 143 | - cd ${DISTDIR} || false 144 | - find . -maxdepth 1 -name '*.tar.gz' -exec tar -xvf '{}' \; 145 | # Generate cabal.project 146 | - rm -rf cabal.project cabal.project.local cabal.project.freeze 147 | - touch cabal.project 148 | - | 149 | echo 'packages: "ALUT-*/*.cabal"' >> cabal.project 150 | - | 151 | echo "write-ghc-environment-files: always" >> cabal.project 152 | - "for pkg in $($HCPKG list --simple-output); do echo $pkg | sed 's/-[^-]*$//' | (grep -vE -- '^(ALUT)$' || true) | sed 's/^/constraints: /' | sed 's/$/ installed/' >> cabal.project.local; done" 153 | - cat cabal.project || true 154 | - cat cabal.project.local || true 155 | # Building... 156 | # this builds all libraries and executables (without tests/benchmarks) 157 | - ${CABAL} v2-build -w ${HC} --disable-tests --disable-benchmarks all | color_cabal_output 158 | # Building with tests and benchmarks... 159 | # build & run tests, build benchmarks 160 | - ${CABAL} v2-build -w ${HC} ${TEST} ${BENCH} all | color_cabal_output 161 | # cabal check... 162 | - (cd ALUT-* && ${CABAL} -vnormal check) 163 | # haddock... 164 | - ${CABAL} v2-haddock -w ${HC} ${TEST} ${BENCH} all | color_cabal_output 165 | # Building without installed constraints for packages in global-db... 166 | - rm -f cabal.project.local 167 | - ${CABAL} v2-build -w ${HC} --disable-tests --disable-benchmarks all | color_cabal_output 168 | 169 | # REGENDATA ["ALUT.cabal","--output",".travis.yml","--apt","libopenal-dev","--apt","libalut-dev","--apt","freeglut3-dev"] 170 | # EOF 171 | -------------------------------------------------------------------------------- /ALUT.cabal: -------------------------------------------------------------------------------- 1 | name: ALUT 2 | version: 2.4.0.3 3 | synopsis: A binding for the OpenAL Utility Toolkit 4 | description: 5 | A Haskell binding for the OpenAL Utility Toolkit, which makes 6 | managing of OpenAL contexts, loading sounds in various formats 7 | and creating waveforms very easy. For more information about the 8 | C library on which this binding is based, please see: 9 | . 10 | homepage: https://github.com/haskell-openal/ALUT 11 | bug-reports: https://github.com/haskell-openal/ALUT/issues 12 | copyright: Copyright (C) 2005-2016 Sven Panne 13 | license: BSD3 14 | license-file: LICENSE 15 | author: Sven Panne 16 | maintainer: Sven Panne 17 | category: Sound 18 | build-type: Simple 19 | tested-with: 20 | GHC == 7.0.4 21 | GHC == 7.2.2 22 | GHC == 7.4.2 23 | GHC == 7.6.3 24 | GHC == 7.8.4 25 | GHC == 7.10.3 26 | GHC == 8.0.2 27 | GHC == 8.2.2 28 | GHC == 8.4.3 29 | GHC == 8.6.5 30 | GHC == 8.8.1 31 | cabal-version: >= 1.10 32 | extra-source-files: 33 | CHANGELOG.md 34 | README.md 35 | examples/TestSuite/file1.wav 36 | examples/TestSuite/file2.au 37 | examples/TestSuite/file3.raw 38 | 39 | flag UseNativeWindowsLibraries 40 | description: 41 | When compiling under Windows, use the native libraries instead of e.g. the 42 | ones coming with Cygwin. 43 | 44 | flag BuildExamples 45 | description: Build various ALUT examples. 46 | default: False 47 | 48 | library 49 | exposed-modules: 50 | Sound.ALUT 51 | Sound.ALUT.Initialization 52 | Sound.ALUT.Loaders 53 | Sound.ALUT.Sleep 54 | Sound.ALUT.Version 55 | other-modules: 56 | Sound.ALUT.Config 57 | Sound.ALUT.Constants 58 | Sound.ALUT.Errors 59 | hs-source-dirs: src 60 | ghc-options: -Wall 61 | if impl(ghc > 8) 62 | ghc-options: -Wcompat 63 | build-depends: 64 | base >= 3 && < 5, 65 | transformers >= 0.2 && < 0.6, 66 | StateVar >= 1.1 && < 1.3, 67 | OpenAL >= 1.7 && < 1.8 68 | default-language: Haskell2010 69 | other-extensions: CPP 70 | if os(windows) && flag(UseNativeWindowsLibraries) 71 | if arch(i386) 72 | cpp-options: "-DCALLCONV=stdcall" 73 | else 74 | cpp-options: "-DCALLCONV=ccall" 75 | extra-libraries: alut 76 | else 77 | cpp-options: "-DCALLCONV=ccall" 78 | if os(ios) 79 | frameworks: ALUT 80 | else 81 | extra-libraries: alut 82 | 83 | executable Basic-HelloWorld 84 | if !flag(BuildExamples) 85 | buildable: False 86 | main-is: HelloWorld.hs 87 | build-depends: base >= 3 && < 5, ALUT 88 | hs-source-dirs: examples/Basic 89 | default-language: Haskell2010 90 | ghc-options: -Wall 91 | 92 | executable Basic-OpenALInfo 93 | if !flag(BuildExamples) 94 | buildable: False 95 | main-is: OpenALInfo.hs 96 | build-depends: base >= 3 && < 5, pretty, ALUT 97 | hs-source-dirs: examples/Basic 98 | default-language: Haskell2010 99 | ghc-options: -Wall 100 | 101 | executable Basic-PlayFile 102 | if !flag(BuildExamples) 103 | buildable: False 104 | main-is: PlayFile.hs 105 | build-depends: base >= 3 && < 5, ALUT 106 | hs-source-dirs: examples/Basic 107 | default-language: Haskell2010 108 | ghc-options: -Wall 109 | 110 | executable TestSuite-TestErrorStuff 111 | if !flag(BuildExamples) 112 | buildable: False 113 | main-is: TestErrorStuff.hs 114 | build-depends: base >= 3 && < 5, ALUT 115 | hs-source-dirs: examples/TestSuite 116 | default-language: Haskell2010 117 | ghc-options: -Wall 118 | 119 | executable TestSuite-TestFileLoader 120 | if !flag(BuildExamples) 121 | buildable: False 122 | main-is: TestFileLoader.hs 123 | build-depends: base >= 3 && < 5, ALUT 124 | hs-source-dirs: examples/TestSuite 125 | default-language: Haskell2010 126 | ghc-options: -Wall 127 | 128 | executable TestSuite-TestMemoryLoader 129 | if !flag(BuildExamples) 130 | buildable: False 131 | main-is: TestMemoryLoader.hs 132 | build-depends: base >= 3 && < 5, ALUT 133 | hs-source-dirs: examples/TestSuite 134 | default-language: Haskell2010 135 | ghc-options: -Wall 136 | 137 | executable TestSuite-TestVersion 138 | if !flag(BuildExamples) 139 | buildable: False 140 | main-is: TestVersion.hs 141 | build-depends: base >= 3 && < 5, ALUT 142 | hs-source-dirs: examples/TestSuite 143 | default-language: Haskell2010 144 | ghc-options: -Wall 145 | 146 | executable TestSuite-TestWaveforms 147 | if !flag(BuildExamples) 148 | buildable: False 149 | main-is: TestWaveforms.hs 150 | build-depends: base >= 3 && < 5, ALUT 151 | hs-source-dirs: examples/TestSuite 152 | default-language: Haskell2010 153 | ghc-options: -Wall 154 | 155 | source-repository head 156 | type: git 157 | location: https://github.com/haskell-openal/ALUT.git 158 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2.4.0.3 2 | ------- 3 | * Relaxed upper version bound for `StateVar`. 4 | 5 | 2.4.0.2 6 | ------- 7 | * Build examples via cabal. 8 | 9 | 2.4.0.1 10 | ------- 11 | * Relaxed upper version bound for `transformers`. 12 | * Added CHANGELOG.md to distribution. 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2005-2016, Sven Panne 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 14 | 3. Neither the name of the author nor the names of its contributors may be 15 | used to endorse or promote products derived from this software without 16 | specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | POSSIBILITY OF SUCH DAMAGE. 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ALUT [![Hackage](https://img.shields.io/hackage/v/ALUT.svg)](https://hackage.haskell.org/package/ALUT) [![Stackage LTS](https://www.stackage.org/package/ALUT/badge/lts)](https://www.stackage.org/lts/package/ALUT) [![Stackage nightly](https://www.stackage.org/package/ALUT/badge/nightly)](https://www.stackage.org/nightly/package/ALUT) [![Build Status](https://img.shields.io/travis/haskell-openal/ALUT/master.svg)](https://travis-ci.org/haskell-openal/ALUT) 2 | 3 | 4 | A Haskell binding for the OpenAL Utility Toolkit, which makes managing of OpenAL contexts, loading sounds in various formats and creating waveforms very easy. You can find the required ALUT library e.g. [here on GitHub](https://github.com/vancegroup/freealut). 5 | -------------------------------------------------------------------------------- /Setup.hs: -------------------------------------------------------------------------------- 1 | import Distribution.Simple 2 | main = defaultMain 3 | -------------------------------------------------------------------------------- /examples/Basic/HelloWorld.hs: -------------------------------------------------------------------------------- 1 | {- 2 | HelloWorld.hs (adapted from hello_world.c in freealut) 3 | Copyright (c) Sven Panne 2005-2016 4 | This file is part of the ALUT package & distributed under a BSD-style license. 5 | See the file LICENSE. 6 | -} 7 | 8 | import Sound.ALUT 9 | 10 | -- This is the Haskell version of the 'Hello World' program from the ALUT 11 | -- reference manual. 12 | 13 | main :: IO () 14 | main = 15 | withProgNameAndArgs runALUT $ \_progName _args -> do 16 | helloBuffer <- createBuffer HelloWorld 17 | helloSource <- genObjectName 18 | buffer helloSource $= Just helloBuffer 19 | play [helloSource] 20 | sleep 1 21 | -------------------------------------------------------------------------------- /examples/Basic/OpenALInfo.hs: -------------------------------------------------------------------------------- 1 | {- 2 | OpenALInfo.hs (modeled after OpenGL's glxinfo) 3 | Copyright (c) Sven Panne 2005-2016 4 | This file is part of the ALUT package & distributed under a BSD-style license. 5 | See the file LICENSE. 6 | -} 7 | 8 | import Text.PrettyPrint 9 | import Sound.ALUT 10 | 11 | -- This program prints some basic information about ALC and AL. 12 | 13 | printVar :: (a -> Doc) -> GettableStateVar a -> IO () 14 | printVar format var = get var >>= putStrLn . render . format 15 | 16 | printStringVar :: String -> GettableStateVar String -> IO () 17 | printStringVar header = printVar (\v -> text header <> colon <+> text v) 18 | 19 | printStringListVar :: String -> GettableStateVar [String] -> IO () 20 | printStringListVar header = 21 | printVar (\xs -> text header <> colon $$ 22 | nest 4 (fsep (punctuate comma (map text xs)))) 23 | 24 | main :: IO () 25 | main = 26 | withProgNameAndArgs runALUT $ \_progName _args -> do 27 | Just ctx <- get currentContext 28 | Just dev <- get (contextsDevice ctx) 29 | printStringVar "ALC version" alcVersion 30 | printStringListVar "ALC extensions" (alcExtensions dev) 31 | printStringVar "AL version" alVersion 32 | printStringVar "AL renderer" alRenderer 33 | printStringVar "AL vendor" alVendor 34 | printStringListVar "AL extensions" alExtensions 35 | -------------------------------------------------------------------------------- /examples/Basic/PlayFile.hs: -------------------------------------------------------------------------------- 1 | {- 2 | PlayFile.hs (adapted from playfile.c in freealut) 3 | Copyright (c) Sven Panne 2005-2016 4 | This file is part of the ALUT package & distributed under a BSD-style license. 5 | See the file LICENSE. 6 | -} 7 | 8 | import Control.Monad ( when, unless ) 9 | import Data.List ( intersperse ) 10 | import Sound.ALUT 11 | import System.Exit ( exitFailure ) 12 | import System.IO ( hPutStrLn, stderr ) 13 | 14 | -- This program loads and plays a variety of files. 15 | 16 | playFile :: FilePath -> IO () 17 | playFile fileName = do 18 | -- Create an AL buffer from the given sound file. 19 | buf <- createBuffer (File fileName) 20 | 21 | -- Generate a single source, attach the buffer to it and start playing. 22 | source <- genObjectName 23 | buffer source $= Just buf 24 | play [source] 25 | 26 | -- Normally nothing should go wrong above, but one never knows... 27 | errs <- get alErrors 28 | unless (null errs) $ do 29 | hPutStrLn stderr (concat (intersperse "," [ d | ALError _ d <- errs ])) 30 | exitFailure 31 | 32 | -- Check every 0.1 seconds if the sound is still playing. 33 | let waitWhilePlaying = do 34 | sleep 0.1 35 | state <- get (sourceState source) 36 | when (state == Playing) $ 37 | waitWhilePlaying 38 | waitWhilePlaying 39 | 40 | main :: IO () 41 | main = do 42 | -- Initialise ALUT and eat any ALUT-specific commandline flags. 43 | withProgNameAndArgs runALUT $ \progName args -> do 44 | 45 | -- Check for correct usage. 46 | unless (length args == 1) $ do 47 | hPutStrLn stderr ("usage: " ++ progName ++ " ") 48 | exitFailure 49 | 50 | -- If everything is OK, play the sound file and exit when finished. 51 | playFile (head args) 52 | -------------------------------------------------------------------------------- /examples/TestSuite/TestErrorStuff.hs: -------------------------------------------------------------------------------- 1 | {- 2 | TestErrorStuff.hs (adapted from test_errorstuff.c in freealut) 3 | Copyright (c) Sven Panne 2005-2016 4 | This file is part of the ALUT package & distributed under a BSD-style license. 5 | See the file LICENSE. 6 | -} 7 | 8 | import Control.Exception ( onException ) 9 | import Control.Monad ( void ) 10 | import Sound.ALUT 11 | import System.Exit ( exitFailure, exitWith, ExitCode(ExitSuccess) ) 12 | import System.IO ( hPutStrLn, stderr ) 13 | 14 | -- This is a minimal test for error handling. 15 | 16 | main :: IO () 17 | main = do 18 | void $ withProgNameAndArgs runALUT $ \_progName _args -> 19 | createBuffer (File "no_such_file_in_existance.wav") 20 | `onException` (exitWith ExitSuccess) 21 | hPutStrLn stderr "expected an I/O error" 22 | exitFailure 23 | -------------------------------------------------------------------------------- /examples/TestSuite/TestFileLoader.hs: -------------------------------------------------------------------------------- 1 | {- 2 | TestFileLoader.hs (adapted from test_fileloader.c in freealut) 3 | Copyright (c) Sven Panne 2005-2016 4 | This file is part of the ALUT package & distributed under a BSD-style license. 5 | See the file LICENSE. 6 | -} 7 | 8 | import Control.Monad ( when, unless ) 9 | import Data.List ( intersperse ) 10 | import Sound.ALUT 11 | import System.Exit ( exitFailure ) 12 | import System.IO ( hPutStrLn, stderr ) 13 | 14 | -- This program loads and plays a variety of files, basically an automated 15 | -- version of Basic/PlayFile.hs. 16 | 17 | playFile :: FilePath -> IO () 18 | playFile fileName = do 19 | -- Create an AL buffer from the given sound file. 20 | buf <- createBuffer (File fileName) 21 | 22 | -- Generate a single source, attach the buffer to it and start playing. 23 | source <- genObjectName 24 | buffer source $= Just buf 25 | play [source] 26 | 27 | -- Normally nothing should go wrong above, but one never knows... 28 | errs <- get alErrors 29 | unless (null errs) $ do 30 | hPutStrLn stderr (concat (intersperse "," [ d | ALError _ d <- errs ])) 31 | exitFailure 32 | 33 | -- Check every 0.1 seconds if the sound is still playing. 34 | let waitWhilePlaying = do 35 | sleep 0.1 36 | state <- get (sourceState source) 37 | when (state == Playing) $ 38 | waitWhilePlaying 39 | waitWhilePlaying 40 | 41 | main :: IO () 42 | main = 43 | -- Initialise ALUT and eat any ALUT-specific commandline flags. 44 | withProgNameAndArgs runALUT $ \_progName _args -> do 45 | 46 | -- If everything is OK, play the sound files and exit when finished. 47 | mapM_ playFile [ "file1.wav", "file2.au", "file3.raw" ] 48 | -------------------------------------------------------------------------------- /examples/TestSuite/TestMemoryLoader.hs: -------------------------------------------------------------------------------- 1 | {- 2 | TestMemoryLoader.hs (adapted from test_memoryloader.c in freealut) 3 | Copyright (c) Sven Panne 2005-2016 4 | This file is part of the ALUT package & distributed under a BSD-style license. 5 | See the file LICENSE. 6 | -} 7 | 8 | import Control.Exception ( bracket ) 9 | import Control.Monad ( when, unless ) 10 | import Data.List ( intersperse ) 11 | import Foreign.Marshal.Alloc ( allocaBytes ) 12 | import Sound.ALUT 13 | import System.Exit ( exitFailure ) 14 | import System.IO ( 15 | openBinaryFile, IOMode(ReadMode), hClose, hFileSize, hGetBuf, hPutStrLn, 16 | stderr ) 17 | 18 | -- This program loads and plays a variety of files from memory, basically a 19 | -- modified version of TestFileLoader.hs. 20 | 21 | withFileContents :: FilePath -> (MemoryRegion a -> IO b) -> IO b 22 | withFileContents filePath action = 23 | bracket (openBinaryFile filePath ReadMode) hClose $ \handle -> do 24 | numBytes <- fmap fromIntegral (hFileSize handle) 25 | allocaBytes numBytes $ \buf -> do 26 | bytesRead <- hGetBuf handle buf numBytes 27 | when (bytesRead /= numBytes) $ 28 | ioError (userError "hGetBuf") 29 | action (MemoryRegion buf (fromIntegral numBytes)) 30 | 31 | playFile :: FilePath -> IO () 32 | playFile fileName = do 33 | -- Load the sound file into memory and create an AL buffer from it. 34 | buf <- withFileContents fileName (createBuffer . FileImage) 35 | 36 | -- Generate a single source, attach the buffer to it and start playing. 37 | source <- genObjectName 38 | buffer source $= Just buf 39 | play [source] 40 | 41 | -- Normally nothing should go wrong above, but one never knows... 42 | errs <- get alErrors 43 | unless (null errs) $ do 44 | hPutStrLn stderr (concat (intersperse "," [ d | ALError _ d <- errs ])) 45 | exitFailure 46 | 47 | -- Check every 0.1 seconds if the sound is still playing. 48 | let waitWhilePlaying = do 49 | sleep 0.1 50 | state <- get (sourceState source) 51 | when (state == Playing) $ 52 | waitWhilePlaying 53 | waitWhilePlaying 54 | 55 | main :: IO () 56 | main = 57 | -- Initialise ALUT and eat any ALUT-specific commandline flags. 58 | withProgNameAndArgs runALUT $ \_progName _args -> do 59 | 60 | -- If everything is OK, play the sound files and exit when finished. Note 61 | -- that we can not play raw sound files from memory because the format 62 | -- can't be guessed without a file name. 63 | mapM_ playFile [ "file1.wav", "file2.au" ] 64 | -------------------------------------------------------------------------------- /examples/TestSuite/TestVersion.hs: -------------------------------------------------------------------------------- 1 | {- 2 | TestVersion.hs (adapted from test_version.c in freealut) 3 | Copyright (c) Sven Panne 2005-2016 4 | This file is part of the ALUT package & distributed under a BSD-style license. 5 | See the file LICENSE. 6 | -} 7 | 8 | import Control.Monad ( unless ) 9 | import Sound.ALUT 10 | import System.Exit ( exitFailure ) 11 | import System.IO ( hPutStrLn, stderr ) 12 | 13 | -- This program checks that the version of OpenAL in the library agrees with the 14 | -- header file we're compiled against. 15 | 16 | main :: IO () 17 | main = 18 | withProgNameAndArgs runALUT $ \_progName _args -> do 19 | av <- get alutVersion 20 | unless (av == alutAPIVersion) $ do 21 | hPutStrLn stderr ("WARNING: The ALUT library is version " ++ av ++ ".x but the ALUT binding says it's " ++ alutAPIVersion ++ ".x!") 22 | exitFailure 23 | hPutStrLn stderr ("The ALUT library is at version " ++ av ++ ".x") 24 | -------------------------------------------------------------------------------- /examples/TestSuite/TestWaveforms.hs: -------------------------------------------------------------------------------- 1 | {- 2 | TestWaveforms.hs (adapted from test_waveforms.c in freealut) 3 | Copyright (c) Sven Panne 2005-2016 4 | This file is part of the ALUT package & distributed under a BSD-style license. 5 | See the file LICENSE. 6 | -} 7 | 8 | import Sound.ALUT 9 | 10 | -- This program plays a 440Hz tone using a variety of waveforms. 11 | 12 | playTone :: (Frequency -> Phase -> Duration -> SoundDataSource a) -> IO () 13 | playTone soundDataSource = do 14 | buf <- createBuffer (soundDataSource 440 0 1) 15 | source <- genObjectName 16 | buffer source $= Just buf 17 | play [source] 18 | sleep 1 19 | 20 | main :: IO () 21 | main = 22 | withProgNameAndArgs runALUT $ \_progName _args -> 23 | mapM_ playTone [ Sine, Square, Sawtooth, (const (const WhiteNoise)), Impulse ] 24 | -------------------------------------------------------------------------------- /examples/TestSuite/file1.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haskell-openal/ALUT/98ba9a7f431fd7572b920ba1fbdd0122d3cb84a3/examples/TestSuite/file1.wav -------------------------------------------------------------------------------- /examples/TestSuite/file2.au: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haskell-openal/ALUT/98ba9a7f431fd7572b920ba1fbdd0122d3cb84a3/examples/TestSuite/file2.au -------------------------------------------------------------------------------- /examples/TestSuite/file3.raw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haskell-openal/ALUT/98ba9a7f431fd7572b920ba1fbdd0122d3cb84a3/examples/TestSuite/file3.raw -------------------------------------------------------------------------------- /src/Sound/ALUT.hs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- 2 | -- | 3 | -- Module : Sound.ALUT 4 | -- Copyright : (c) Sven Panne 2005-2016 5 | -- License : BSD3 6 | -- 7 | -- Maintainer : Sven Panne 8 | -- Stability : stable 9 | -- Portability : portable 10 | -- 11 | -- A Haskell binding for the OpenAL Utility Toolkit, which makes managing of 12 | -- OpenAL contexts, loading sounds in various formats and creating waveforms 13 | -- very easy. For more information about the C library on which this binding is 14 | -- based, please see: 15 | -- . 16 | -- 17 | -------------------------------------------------------------------------------- 18 | 19 | module Sound.ALUT ( 20 | module Sound.OpenAL, 21 | 22 | module Sound.ALUT.Initialization, 23 | module Sound.ALUT.Loaders, 24 | module Sound.ALUT.Version, 25 | module Sound.ALUT.Sleep 26 | ) where 27 | 28 | import Sound.OpenAL 29 | 30 | import Sound.ALUT.Initialization 31 | import Sound.ALUT.Loaders 32 | import Sound.ALUT.Version 33 | import Sound.ALUT.Sleep 34 | -------------------------------------------------------------------------------- /src/Sound/ALUT/Config.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE CPP #-} 2 | {-# OPTIONS_HADDOCK hide #-} 3 | -------------------------------------------------------------------------------- 4 | -- | 5 | -- Module : Sound.ALUT.Config 6 | -- Copyright : (c) Sven Panne 2005-2016 7 | -- License : BSD3 8 | -- 9 | -- Maintainer : Sven Panne 10 | -- Stability : stable 11 | -- Portability : portable 12 | -- 13 | -- This purely internal module defines the platform-specific stuff which has 14 | -- been figured out by configure. 15 | -- 16 | -------------------------------------------------------------------------------- 17 | 18 | module Sound.ALUT.Config ( 19 | alut_Init, 20 | alut_InitWithoutContext, 21 | alut_Exit, 22 | 23 | alut_GetError, 24 | alut_GetErrorString, 25 | 26 | alut_CreateBufferFromFile, 27 | alut_CreateBufferFromFileImage, 28 | alut_CreateBufferHelloWorld, 29 | alut_CreateBufferWaveform, 30 | 31 | alut_LoadMemoryFromFile, 32 | alut_LoadMemoryFromFileImage, 33 | alut_LoadMemoryHelloWorld, 34 | alut_LoadMemoryWaveform, 35 | 36 | alut_GetMIMETypes, 37 | 38 | alut_GetMajorVersion, 39 | alut_GetMinorVersion, 40 | 41 | alut_Sleep 42 | ) where 43 | 44 | -------------------------------------------------------------------------------- 45 | 46 | -- Make the foreign imports happy. 47 | import Foreign.C.Types 48 | 49 | import Foreign.C.String ( CString, peekCString ) 50 | import Foreign.Ptr ( Ptr ) 51 | import Sound.OpenAL.AL.BasicTypes ( ALboolean, ALenum, ALfloat, ALint, ALsizei, ALuint ) 52 | 53 | -------------------------------------------------------------------------------- 54 | 55 | foreign import CALLCONV unsafe "alutInit" 56 | alut_Init :: Ptr CInt -> Ptr CString -> IO ALboolean 57 | 58 | -------------------------------------------------------------------------------- 59 | 60 | foreign import CALLCONV unsafe "alutInitWithoutContext" 61 | alut_InitWithoutContext :: Ptr CInt -> Ptr CString -> IO ALboolean 62 | 63 | -------------------------------------------------------------------------------- 64 | 65 | foreign import CALLCONV unsafe "alutExit" 66 | alut_Exit :: IO ALboolean 67 | 68 | -------------------------------------------------------------------------------- 69 | 70 | foreign import CALLCONV unsafe "alutGetError" 71 | alut_GetError :: IO ALenum 72 | 73 | -------------------------------------------------------------------------------- 74 | 75 | alut_GetErrorString :: ALenum -> IO String 76 | alut_GetErrorString e = peekCString =<< alutGetErrorString e 77 | 78 | foreign import CALLCONV unsafe "alutGetErrorString" 79 | alutGetErrorString :: ALenum -> IO CString 80 | 81 | -------------------------------------------------------------------------------- 82 | 83 | foreign import CALLCONV unsafe "alutCreateBufferFromFile" 84 | alut_CreateBufferFromFile :: CString -> IO ALuint 85 | 86 | -------------------------------------------------------------------------------- 87 | 88 | foreign import CALLCONV unsafe "alutCreateBufferFromFileImage" 89 | alut_CreateBufferFromFileImage :: Ptr a -> ALsizei -> IO ALuint 90 | 91 | -------------------------------------------------------------------------------- 92 | 93 | foreign import CALLCONV unsafe "alutCreateBufferHelloWorld" 94 | alut_CreateBufferHelloWorld :: IO ALuint 95 | 96 | -------------------------------------------------------------------------------- 97 | 98 | foreign import CALLCONV unsafe "alutCreateBufferWaveform" 99 | alut_CreateBufferWaveform :: ALenum 100 | -> ALfloat 101 | -> ALfloat 102 | -> ALfloat 103 | -> IO ALuint 104 | 105 | -------------------------------------------------------------------------------- 106 | 107 | foreign import CALLCONV unsafe "alutLoadMemoryFromFile" 108 | alut_LoadMemoryFromFile :: CString 109 | -> Ptr ALenum 110 | -> Ptr ALsizei 111 | -> Ptr ALfloat 112 | -> IO (Ptr b) 113 | 114 | -------------------------------------------------------------------------------- 115 | 116 | foreign import CALLCONV unsafe "alutLoadMemoryFromFileImage" 117 | alut_LoadMemoryFromFileImage :: Ptr a 118 | -> ALsizei 119 | -> Ptr ALenum 120 | -> Ptr ALsizei 121 | -> Ptr ALfloat 122 | -> IO (Ptr b) 123 | 124 | -------------------------------------------------------------------------------- 125 | 126 | foreign import CALLCONV unsafe "alutLoadMemoryHelloWorld" 127 | alut_LoadMemoryHelloWorld :: Ptr ALenum 128 | -> Ptr ALsizei 129 | -> Ptr ALfloat 130 | -> IO (Ptr b) 131 | 132 | -------------------------------------------------------------------------------- 133 | 134 | foreign import CALLCONV unsafe "alutLoadMemoryWaveform" 135 | alut_LoadMemoryWaveform :: ALenum 136 | -> ALfloat 137 | -> ALfloat 138 | -> ALfloat 139 | -> Ptr ALenum 140 | -> Ptr ALsizei 141 | -> Ptr ALfloat 142 | -> IO (Ptr b) 143 | 144 | -------------------------------------------------------------------------------- 145 | 146 | foreign import CALLCONV unsafe "alutGetMIMETypes" 147 | alut_GetMIMETypes :: ALenum -> IO CString 148 | 149 | -------------------------------------------------------------------------------- 150 | 151 | foreign import CALLCONV unsafe "alutGetMajorVersion" 152 | alut_GetMajorVersion :: IO ALint 153 | 154 | -------------------------------------------------------------------------------- 155 | 156 | foreign import CALLCONV unsafe "alutGetMinorVersion" 157 | alut_GetMinorVersion :: IO ALint 158 | 159 | -------------------------------------------------------------------------------- 160 | 161 | foreign import CALLCONV unsafe "alutSleep" 162 | alut_Sleep :: ALfloat -> IO ALboolean 163 | -------------------------------------------------------------------------------- /src/Sound/ALUT/Constants.hs: -------------------------------------------------------------------------------- 1 | {-# OPTIONS_HADDOCK hide #-} 2 | -------------------------------------------------------------------------------- 3 | -- | 4 | -- Module : Sound.ALUT.Constants 5 | -- Copyright : (c) Sven Panne 2005-2016 6 | -- License : BSD3 7 | -- 8 | -- Maintainer : Sven Panne 9 | -- Stability : stable 10 | -- Portability : portable 11 | -- 12 | -------------------------------------------------------------------------------- 13 | 14 | module Sound.ALUT.Constants where 15 | 16 | import Sound.OpenAL.AL.BasicTypes ( ALint, ALenum ) 17 | 18 | -------------------------------------------------------------------------------- 19 | 20 | alut_API_MAJOR_VERSION, alut_API_MINOR_VERSION :: ALint 21 | alut_API_MAJOR_VERSION = 1 22 | alut_API_MINOR_VERSION = 1 23 | 24 | -------------------------------------------------------------------------------- 25 | 26 | alut_WAVEFORM_SINE, alut_WAVEFORM_SQUARE, alut_WAVEFORM_SAWTOOTH, 27 | alut_WAVEFORM_IMPULSE, alut_WAVEFORM_WHITENOISE :: ALenum 28 | alut_WAVEFORM_SINE = 0x100 29 | alut_WAVEFORM_SQUARE = 0x101 30 | alut_WAVEFORM_SAWTOOTH = 0x102 31 | alut_WAVEFORM_WHITENOISE = 0x103 32 | alut_WAVEFORM_IMPULSE = 0x104 33 | 34 | -------------------------------------------------------------------------------- 35 | 36 | alut_LOADER_BUFFER, alut_LOADER_MEMORY :: ALenum 37 | alut_LOADER_BUFFER = 0x300 38 | alut_LOADER_MEMORY = 0x301 39 | -------------------------------------------------------------------------------- /src/Sound/ALUT/Errors.hs: -------------------------------------------------------------------------------- 1 | {-# OPTIONS_HADDOCK hide #-} 2 | -------------------------------------------------------------------------------- 3 | -- | 4 | -- Module : Sound.ALUT.Errors 5 | -- Copyright : (c) Sven Panne 2005-2016 6 | -- License : BSD3 7 | -- 8 | -- Maintainer : Sven Panne 9 | -- Stability : stable 10 | -- Portability : portable 11 | -- 12 | -------------------------------------------------------------------------------- 13 | 14 | module Sound.ALUT.Errors ( 15 | throwIfALfalse, throwIfNullPtr, makeBuffer 16 | ) where 17 | 18 | import Control.Monad ( void, when ) 19 | import Data.Maybe ( fromJust, isNothing ) 20 | import Foreign.Ptr ( Ptr, nullPtr ) 21 | import Sound.OpenAL.AL.BasicTypes ( ALboolean, ALuint ) 22 | import Sound.OpenAL.AL.Buffer ( Buffer ) 23 | import Sound.OpenAL.AL.Extensions ( unmarshalALboolean, unmarshalBuffer ) 24 | 25 | import Sound.ALUT.Config ( alut_GetError, alut_GetErrorString ) 26 | 27 | -------------------------------------------------------------------------------- 28 | 29 | throwIf :: (a -> Bool) -> String -> IO a -> IO a 30 | throwIf failurePredicate name action = do 31 | returnValue <- action 32 | when (failurePredicate returnValue) $ do 33 | description <- alut_GetErrorString =<< alut_GetError 34 | ioError (userError (name ++ ": " ++ description)) 35 | return returnValue 36 | 37 | -------------------------------------------------------------------------------- 38 | 39 | throwIfALfalse :: String -> IO ALboolean -> IO () 40 | throwIfALfalse name action = 41 | void $ throwIf (not . unmarshalALboolean) name action 42 | 43 | -------------------------------------------------------------------------------- 44 | 45 | throwIfNullPtr :: String -> IO (Ptr a) -> IO (Ptr a) 46 | throwIfNullPtr = throwIf (== nullPtr) 47 | 48 | -------------------------------------------------------------------------------- 49 | 50 | makeBuffer :: String -> IO ALuint -> IO Buffer 51 | makeBuffer name = 52 | fmap fromJust . throwIf isNothing name . fmap unmarshalBuffer 53 | -------------------------------------------------------------------------------- /src/Sound/ALUT/Initialization.hs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- 2 | -- | 3 | -- Module : Sound.ALUT.Initialization 4 | -- Copyright : (c) Sven Panne 2005-2016 5 | -- License : BSD3 6 | -- 7 | -- Maintainer : Sven Panne 8 | -- Stability : stable 9 | -- Portability : portable 10 | -- 11 | -------------------------------------------------------------------------------- 12 | 13 | module Sound.ALUT.Initialization ( 14 | ArgumentConsumer, Runner, runALUT, runALUTUsingCurrentContext, 15 | withProgNameAndArgs 16 | ) where 17 | 18 | import Control.Monad.IO.Class ( MonadIO(..) ) 19 | import Data.List ( genericLength ) 20 | import Foreign.C.String ( CString, withCString, peekCString ) 21 | import Foreign.C.Types ( CInt ) 22 | import Foreign.Marshal.Array ( withArray0, peekArray ) 23 | import Foreign.Marshal.Utils ( with, withMany ) 24 | import Foreign.Ptr ( Ptr, nullPtr ) 25 | import Foreign.Storable ( Storable(peek) ) 26 | import Sound.OpenAL.AL.BasicTypes ( ALboolean ) 27 | import System.Environment ( getProgName, getArgs ) 28 | 29 | import Sound.ALUT.Config 30 | import Sound.ALUT.Errors 31 | 32 | -------------------------------------------------------------------------------- 33 | 34 | type ArgumentConsumer a = String -> [String] -> a 35 | 36 | type Runner m a = ArgumentConsumer (m a) -> m a 37 | 38 | -------------------------------------------------------------------------------- 39 | 40 | runALUT :: MonadIO m => ArgumentConsumer (Runner m a) 41 | runALUT = runner "runALUT" alut_Init 42 | 43 | -------------------------------------------------------------------------------- 44 | 45 | runALUTUsingCurrentContext :: MonadIO m => ArgumentConsumer (Runner m a) 46 | runALUTUsingCurrentContext = 47 | runner "runALUTUsingCurrentContext" alut_InitWithoutContext 48 | 49 | -------------------------------------------------------------------------------- 50 | 51 | runner :: MonadIO m => String -> (Ptr CInt -> Ptr CString -> IO ALboolean) -> String 52 | -> [String] -> Runner m a 53 | runner name initAction progName args action = do 54 | argv <- liftIO $ foo name initAction progName args 55 | result <- action (head argv) (tail argv) 56 | liftIO $ throwIfALfalse name alut_Exit 57 | return result 58 | 59 | foo :: String -> (Ptr CInt -> Ptr CString -> IO ALboolean) -> String -> [String] -> IO [String] 60 | foo name initAction progName args = 61 | with (1 + genericLength args) $ \argcBuf -> 62 | withMany withCString (progName : args) $ \argvPtrs -> 63 | withArray0 nullPtr argvPtrs $ \argvBuf -> do 64 | throwIfALfalse name $ initAction argcBuf argvBuf 65 | newArgc <- peek argcBuf 66 | newArgvPtrs <- peekArray (fromIntegral newArgc) argvBuf 67 | mapM peekCString newArgvPtrs 68 | 69 | -------------------------------------------------------------------------------- 70 | 71 | withProgNameAndArgs :: MonadIO m => (ArgumentConsumer (Runner m a)) -> Runner m a 72 | withProgNameAndArgs alutRunner action = do 73 | n <- liftIO getProgName 74 | a <- liftIO getArgs 75 | alutRunner n a action 76 | -------------------------------------------------------------------------------- /src/Sound/ALUT/Loaders.hs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- 2 | -- | 3 | -- Module : Sound.ALUT.Loaders 4 | -- Copyright : (c) Sven Panne 2005-2016 5 | -- License : BSD3 6 | -- 7 | -- Maintainer : Sven Panne 8 | -- Stability : stable 9 | -- Portability : portable 10 | -- 11 | -------------------------------------------------------------------------------- 12 | 13 | module Sound.ALUT.Loaders ( 14 | Phase, Duration, SoundDataSource(..), 15 | createBuffer, createBufferData, 16 | bufferMIMETypes, bufferDataMIMETypes 17 | ) where 18 | 19 | import Control.Monad.IO.Class ( MonadIO(..) ) 20 | import Data.StateVar ( GettableStateVar, makeGettableStateVar ) 21 | import Foreign.C.String ( peekCString, withCString ) 22 | import Foreign.Marshal.Alloc ( alloca ) 23 | import Foreign.Ptr ( Ptr ) 24 | import Foreign.Storable ( peek ) 25 | import Sound.OpenAL.AL.BasicTypes 26 | import Sound.OpenAL.AL.Buffer ( Buffer, MemoryRegion(..), BufferData(..) ) 27 | import Sound.OpenAL.AL.Extensions ( unmarshalFormat ) 28 | import Sound.OpenAL.ALC.Context ( Frequency ) 29 | 30 | import Sound.ALUT.Config 31 | import Sound.ALUT.Constants 32 | import Sound.ALUT.Errors 33 | 34 | -------------------------------------------------------------------------------- 35 | 36 | type Phase = Float 37 | 38 | type Duration = Float 39 | 40 | data SoundDataSource a = 41 | File FilePath 42 | | FileImage (MemoryRegion a) 43 | | HelloWorld 44 | | Sine Frequency Phase Duration 45 | | Square Frequency Phase Duration 46 | | Sawtooth Frequency Phase Duration 47 | | Impulse Frequency Phase Duration 48 | | WhiteNoise Duration 49 | deriving ( Eq, Ord, Show ) 50 | 51 | -------------------------------------------------------------------------------- 52 | 53 | createBuffer :: MonadIO m => SoundDataSource a -> m Buffer 54 | createBuffer src = liftIO $ makeBuffer "createBuffer" $ case src of 55 | File filePath -> withCString filePath alut_CreateBufferFromFile 56 | FileImage (MemoryRegion buf size) -> alut_CreateBufferFromFileImage buf size 57 | HelloWorld -> alut_CreateBufferHelloWorld 58 | Sine f p d -> createBufferWaveform alut_WAVEFORM_SINE f p d 59 | Square f p d -> createBufferWaveform alut_WAVEFORM_SQUARE f p d 60 | Sawtooth f p d -> createBufferWaveform alut_WAVEFORM_SAWTOOTH f p d 61 | Impulse f p d -> createBufferWaveform alut_WAVEFORM_IMPULSE f p d 62 | WhiteNoise d -> createBufferWaveform alut_WAVEFORM_WHITENOISE 1 0 d 63 | 64 | createBufferWaveform :: ALenum -> Float -> Float -> Float -> IO ALuint 65 | createBufferWaveform w f p d = 66 | alut_CreateBufferWaveform w (realToFrac f) (realToFrac p) (realToFrac d) 67 | 68 | -------------------------------------------------------------------------------- 69 | 70 | createBufferData :: MonadIO m => SoundDataSource a -> m (BufferData b) 71 | createBufferData src = liftIO $ case src of 72 | File filePath -> withCString filePath $ \fp -> loadWith (alut_LoadMemoryFromFile fp) 73 | FileImage (MemoryRegion buf size) -> loadWith (alut_LoadMemoryFromFileImage buf size) 74 | HelloWorld -> loadWith alut_LoadMemoryHelloWorld 75 | Sine f p d -> loadWith (loadMemoryWaveform alut_WAVEFORM_SINE f p d) 76 | Square f p d -> loadWith (loadMemoryWaveform alut_WAVEFORM_SQUARE f p d) 77 | Sawtooth f p d -> loadWith (loadMemoryWaveform alut_WAVEFORM_SAWTOOTH f p d) 78 | Impulse f p d -> loadWith (loadMemoryWaveform alut_WAVEFORM_IMPULSE f p d) 79 | WhiteNoise d -> loadWith (loadMemoryWaveform alut_WAVEFORM_WHITENOISE 1 0 d) 80 | 81 | loadMemoryWaveform :: ALenum -> Float -> Float -> Float -> Ptr ALenum -> Ptr ALsizei -> Ptr ALfloat -> IO (Ptr b) 82 | loadMemoryWaveform w f p d = 83 | alut_LoadMemoryWaveform w (realToFrac f) (realToFrac p) (realToFrac d) 84 | 85 | loadWith :: (Ptr ALenum -> Ptr ALsizei -> Ptr ALfloat -> IO (Ptr b)) -> IO (BufferData b) 86 | loadWith loader = 87 | alloca $ \formatBuf -> 88 | alloca $ \sizeBuf -> 89 | alloca $ \frequencyBuf -> do 90 | buf <- throwIfNullPtr "createBufferData" $ 91 | loader formatBuf sizeBuf frequencyBuf 92 | format <- peek formatBuf 93 | size <- peek sizeBuf 94 | frequency <- peek frequencyBuf 95 | return $ BufferData (MemoryRegion buf size) (unmarshalFormat format) (realToFrac frequency) 96 | 97 | -------------------------------------------------------------------------------- 98 | 99 | bufferMIMETypes :: GettableStateVar [String] 100 | bufferMIMETypes = mimeTypes "bufferMIMETypes" alut_LOADER_BUFFER 101 | 102 | bufferDataMIMETypes :: GettableStateVar [String] 103 | bufferDataMIMETypes = mimeTypes "bufferDataMIMETypes" alut_LOADER_MEMORY 104 | 105 | mimeTypes :: String -> ALenum -> GettableStateVar [String] 106 | mimeTypes name loaderType = 107 | makeGettableStateVar $ do 108 | ts <- throwIfNullPtr name $ alut_GetMIMETypes loaderType 109 | fmap (splitBy (== ',')) $ peekCString ts 110 | 111 | splitBy :: (a -> Bool) -> [a] -> [[a]] 112 | splitBy _ [] = [] 113 | splitBy p xs = case break p xs of 114 | (ys, [] ) -> [ys] 115 | (ys, _:zs) -> ys : splitBy p zs 116 | -------------------------------------------------------------------------------- /src/Sound/ALUT/Sleep.hs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- 2 | -- | 3 | -- Module : Sound.ALUT.Sleep 4 | -- Copyright : (c) Sven Panne 2005-2016 5 | -- License : BSD3 6 | -- 7 | -- Maintainer : Sven Panne 8 | -- Stability : stable 9 | -- Portability : portable 10 | -- 11 | -------------------------------------------------------------------------------- 12 | 13 | module Sound.ALUT.Sleep ( 14 | sleep 15 | ) where 16 | 17 | import Control.Monad.IO.Class ( MonadIO(..) ) 18 | 19 | import Sound.ALUT.Config 20 | import Sound.ALUT.Errors 21 | import Sound.ALUT.Loaders 22 | 23 | -------------------------------------------------------------------------------- 24 | 25 | sleep :: MonadIO m => Duration -> m () 26 | sleep = liftIO . throwIfALfalse "sleep" . alut_Sleep . realToFrac 27 | -------------------------------------------------------------------------------- /src/Sound/ALUT/Version.hs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- 2 | -- | 3 | -- Module : Sound.ALUT.Version 4 | -- Copyright : (c) Sven Panne 2005-2016 5 | -- License : BSD3 6 | -- 7 | -- Maintainer : Sven Panne 8 | -- Stability : stable 9 | -- Portability : portable 10 | -- 11 | -------------------------------------------------------------------------------- 12 | 13 | module Sound.ALUT.Version ( 14 | alutAPIVersion, alutVersion 15 | ) where 16 | 17 | import Control.Monad ( liftM2 ) 18 | import Data.StateVar ( GettableStateVar, makeGettableStateVar ) 19 | import Sound.OpenAL.AL.BasicTypes ( ALint ) 20 | 21 | import Sound.ALUT.Config 22 | import Sound.ALUT.Constants 23 | 24 | -------------------------------------------------------------------------------- 25 | 26 | alutAPIVersion :: String 27 | alutAPIVersion = makeVersionString alut_API_MAJOR_VERSION alut_API_MINOR_VERSION 28 | 29 | makeVersionString :: ALint -> ALint -> String 30 | makeVersionString major minor = show major ++ "." ++ show minor 31 | 32 | -------------------------------------------------------------------------------- 33 | 34 | alutVersion :: GettableStateVar String 35 | alutVersion = 36 | makeGettableStateVar $ 37 | liftM2 makeVersionString alut_GetMajorVersion alut_GetMinorVersion 38 | --------------------------------------------------------------------------------