X-Git-Url: http://nitlanguage.org diff --git a/lib/linux/audio.nit b/lib/linux/audio.nit index 85f572a..4b8fdb1 100644 --- a/lib/linux/audio.nit +++ b/lib/linux/audio.nit @@ -14,23 +14,118 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Linux audio implementation +# `app::audio` implementation for GNU/Linux using SDL2 mixer module audio import app::audio +import sdl2::mixer import linux redef class PlayableAudio + redef var error = null - redef fun play do - if path.has_suffix(".wav") then - sys.system "aplay -q {app.assets_dir}{path} &" - else if path.has_suffix(".mp3") then - sys.system "mpg123 -q {app.assets_dir}{path} &" + # Real file system path to this asset + private fun fs_path: String do return app.assets_dir / path + + # Does `fs_path` exist? + private fun fs_path_exists: Bool + do + if not fs_path.file_exists then + error = new Error("Failed to load audio '{path}': file not found") + return false end + return true + end +end + +redef class Sound + + private var native: nullable MixChunk = null + + redef fun load + do + if not fs_path_exists then return + + # SDL2 mixer load + var native = mix.load_wav(fs_path.to_cstring) + if native.address_is_null then + error = new Error("Failed to load sound '{path}': {mix.error}") + return + end + + self.native = native + end + + redef fun play do play_channel(-1, 0) + + # Play this sound on `channel` (or any channel if -1) and return the channel + # + # Repeat the sound `loops` times, `loops == 0` plays it once, + # `loops == 1` plays it twice and `loops == -1` loops infinitely. + fun play_channel(channel, loops: Int): Int + do + var native = native + + if native == null and error == null then + # Lazy load + load + + # Auto print errors on lazy loading only + var error = error + if error != null then print_error error + end + + # If there's an error, silently skip + if error != null then return -1 + native = self.native + assert native != null + + # Play on any available channel + return mix.play_channel(channel, native, loops) end +end + +redef class Music + + private var native: nullable MixMusic = null + + redef fun load + do + if not fs_path_exists then return + + # SDL2 mixer load + var native = mix.load_mus(fs_path.to_cstring) + if native.address_is_null then + error = new Error("Failed to load music '{path}': {mix.error}") + return + end + + self.native = native + end + + redef fun play + do + var native = native + + if native == null and error == null then + # Lazy load + load + + # Auto print errors on lazy loading only + var error = error + if error != null then print_error error + end + + # If there's an error, silently skip + if error != null then return + native = self.native + assert native != null + + # Play looping + mix.play_music(native, -1) + end + + redef fun pause do mix.pause_music - redef fun load do end - redef fun pause do end - redef fun resume do end + redef fun resume do mix.resume_music end