+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# SDL2 mixer with sample/sounds and music
+#
+# C API documentation: https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html
+module mixer is pkgconfig "SDL2_mixer"
+
+import sdl2_base
+
+`{
+ #include "SDL2/SDL_mixer.h"
+`}
+
+redef class Sys
+ # SDL2 mixer services
+ var mix = new Mix is lazy
+end
+
+# SDL2 mixer services
+class Mix
+ # Initialize supports for loading formats in `flags`
+ #
+ # Returns the initialized supports.
+ fun initialize(flags: MixInitFlags): MixInitFlags `{
+ return Mix_Init(flags);
+ `}
+
+ # FLAC format support, for `initialize`
+ fun flac: MixInitFlags `{ return MIX_INIT_FLAC; `}
+
+ # MOD format support, for `initialize`
+ fun mod: MixInitFlags `{ return MIX_INIT_MOD; `}
+
+ # MP3 format support, for `initialize`
+ fun mp3: MixInitFlags `{ return MIX_INIT_MP3; `}
+
+ # OGG format support, for `initialize`
+ fun ogg: MixInitFlags `{ return MIX_INIT_OGG; `}
+
+ # Clean up all dynamically loaded library handles
+ #
+ # May be called after loading all the sounds.
+ fun quit `{ Mix_Quit(); `}
+
+ # Initialize and configure the mixer API
+ #
+ # Playback is configured with:
+ # * The output sample `frequency`, in samples per second (Hz).
+ # * The output sample `format`, may be `mix_default_format`.
+ # * The number of sound `channels`, 1 for mono or 2 for stereo.
+ # * The number of bytes used by output sample size as `chunk_size`.
+ fun open_audio(frequency: Int, format: MixFormat, channels, chunk_size: Int): Bool `{
+ return Mix_OpenAudio(frequency, format, channels, chunk_size) == 0;
+ `}
+
+ # Default frequency for `open_audio` (22050)
+ fun default_frequency: Int `{ return MIX_DEFAULT_FREQUENCY; `}
+
+ # Default format for `open_audio`
+ fun default_format: MixFormat `{ return MIX_DEFAULT_FORMAT; `}
+ # TODO other formats: AUDIO_U8, AUDIO_S8, etc.
+
+ # Shutdown and cleanup the mixer API
+ fun close_audio `{ Mix_CloseAudio(); `}
+
+ # Last error produced by the mixer API
+ fun error: CString `{ return (char*)Mix_GetError(); `}
+
+ # ---
+ # Chunks/sounds
+
+ # Load `file` for use as a sample
+ #
+ # Returns a null pointer on error.
+ #
+ # Can load WAVE, AIFF, RIFF, OGG and VOC files.
+ fun load_wav(file: CString): MixChunk `{ return Mix_LoadWAV(file); `}
+
+ # Play `chunk` on `channel`
+ #
+ # If `channel == -1` the first unreserved channel is used.
+ # The sound is repeated `loops` times, `loops == 0` plays it once and
+ # `loops == -1` loops infinitely.
+ fun play_channel(channel: Int, chunk: MixChunk, loops: Int): Bool `{
+ return Mix_PlayChannel(channel, chunk, loops) == 0;
+ `}
+
+ # Set the chunk volume out of `mix.max_volume` and return the previous value
+ #
+ # Use `volume = -1` to only read the previous value.
+ fun volume_chunk(chunk: MixChunk, volume: Int) `{
+ Mix_VolumeChunk(chunk, volume);
+ `}
+
+ # ---
+ # Music
+
+ # Load music from `file`
+ #
+ # Returns a null pointer on error.
+ #
+ # WAVE, MOD, MIDI, OGG, MP3, FLAC VOC files
+ fun load_mus(file: CString): MixMusic `{ return Mix_LoadMUS(file); `}
+
+ # Play `music` `loops` times
+ #
+ # The music is plays once if `loops == 1` and repeats infinitely if `loops == -1`.
+ fun play_music(music: MixMusic, loops: Int): Bool `{
+ return Mix_PlayMusic(music, loops) == 0;
+ `}
+
+ # Pause music playback
+ fun pause_music `{ Mix_PauseMusic(); `}
+
+ # Resume music playback
+ fun resume_music `{ Mix_ResumeMusic(); `}
+
+ # Set the music volume out of `mix.max_volume` and return the previous value
+ #
+ # Use `volume = -1` to only read the previous value.
+ fun volume_music(volume: Int): Int `{
+ return Mix_VolumeMusic(volume);
+ `}
+
+ # Maximum volume value for `volume_music` and `volume_chunk`
+ fun max_volume: Int `{ return MIX_MAX_VOLUME; `}
+end
+
+# Chunk/sound handle, loaded by `mix.load_wav`
+extern class MixChunk
+ redef fun free `{ Mix_FreeChunk(self); `}
+end
+
+# Music handle, loaded by `mix.load_mus`
+extern class MixMusic
+ redef fun free `{ Mix_FreeMusic(self); `}
+end
+
+# ---
+# Flags & enums
+
+# Flags for `mix.initialize`
+extern class MixInitFlags `{ int `}
+
+ # Binary OR
+ fun | (other: MixInitFlags): MixInitFlags `{ return self | other; `}
+
+ private fun to_i: Int `{ return self; `}
+
+ redef fun ==(o) do return o isa MixInitFlags and o.to_i == to_i
+end
+
+# Sample format for `mix.open_audio`
+extern class MixFormat `{ int `}
+end