note description: "[ chocolate doom i_sdlmusic.c System interface for music. ]" license: "[ Copyright (C) 1993-1996 by id Software, Inc. Copyright (C) 2005-2014 Simon Howard Copyright (C) 2021 Ilgiz Mustafin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ]" class MUSIC_SDL_MODULE inherit MUSIC_MODULE_T EXECUTION_ENVIRONMENT create make feature {NONE} i_main: I_MAIN make (a_i_main: like i_main) do i_main := a_i_main end feature music_initialized: BOOLEAN sdl_was_initialized: BOOLEAN musicpaused: BOOLEAN current_music_volume: INTEGER_32 feature Maxmidlength: INTEGER_32 once Result := 96 * 1024 end feature Music_sdl_module (a_i_main: like i_main): MUSIC_SDL_MODULE once create Result.make (a_i_main) ensure instance_free: class end Sound_devices: ARRAY [INTEGER_32] -- List of sound devices that the music module is used for. once Result := <<{I_SOUND}.snddevice_pas, {I_SOUND}.snddevice_gus, {I_SOUND}.snddevice_waveblaster, {I_SOUND}.snddevice_soundcanvas, {I_SOUND}.snddevice_genmidi, {I_SOUND}.snddevice_awe32>> end poll -- Invoked periodically to poll. do end sdl_is_initialized: BOOLEAN local freq, channels: INTEGER_32 format: NATURAL_16 do Result := {SDL_MIXER_FUNCTIONS_API}.mix_query_spec ($freq, $format.to_pointer, $channels) /= 0 end init: BOOLEAN -- Initialize music subsystem do if sdl_is_initialized then music_initialized := True else if {SDL_FUNCTIONS_API}.sdl_init ({SDL_CONSTANT_API}.sdl_init_audio.to_natural_32) < 0 then print ("Unable to set up sound.%N") elseif {SDL_MIXER_FUNCTIONS_API}.mix_open_audio_device ({I_SOUND}.snd_samplerate, {SDL_AUDIO}.audio_s16sys.to_natural_32, 2, 1024, default_pointer, {SDL_CONSTANT_API}.sdl_audio_allow_frequency_change) < 0 then print ("Error initializing SDL_mixer: " + {MIX_ERROR}.get_error) {SDL_FUNCTIONS_API}.sdl_quit_sub_system ({SDL_CONSTANT_API}.sdl_init_audio.to_natural_32) else {SDL_AUDIO_FUNCTIONS_API}.sdl_pause_audio (0) sdl_was_initialized := True music_initialized := True end end {SDL_MIXER_FUNCTIONS_API}.mix_init ({MIX_INIT_FLAGS_ENUM_API}.mix_init_mid).do_nothing if not i_main.I_sound.Snd_musiccmd.is_empty then if {SDL_MIXER_FUNCTIONS_API}.mix_set_music_cmd ((create {C_STRING}.make (i_main.I_sound.Snd_musiccmd)).item) < 0 then {I_MAIN}.i_error ("Could not Mix_SetMusicCMD " + {MIX_ERROR}.get_error) end end Result := music_initialized end playsong (a_handle: MIX_MUSIC_STRUCT_API; looping: BOOLEAN) -- Start playing a mid local loops: INTEGER_32 do if music_initialized then if attached a_handle as handle or i_main.I_midipipe.midi_server_registered then if looping then loops := -1 else loops := 1 end if {SDL_MIXER_FUNCTIONS_API}.mix_play_music (a_handle, loops) < 0 then {I_MAIN}.i_error ("Could not Mix_PlayMusic " + {MIX_ERROR}.get_error) end end end end is_mid (mem: MANAGED_POINTER): BOOLEAN -- Determine whether memory block is a .mid file do Result := mem.count > 4 and then mem.item.memory_compare ((create {C_STRING}.make ("MThd")).item, 4) end registersong (data: MANAGED_POINTER; len: INTEGER_32): detachable MIX_MUSIC_STRUCT_API -- Register a song handle from data -- Returns a handle that can be used to play the song local filename: STRING_8 do if music_initialized then filename := i_main.M_misc.m_tempfile ("doom.mid") if is_mid (data) and data.count < Maxmidlength then if not i_main.M_misc.m_writefile_managed_pointer (filename, data) then print ("Could not write temp file%N") end else convertmus (data, len, filename) end Result := {MIX}.mix_load_mus (filename) if Result = Void then print ("Error loading midi: " + {MIX_ERROR}.get_error) end if i_main.I_sound.Snd_musiccmd.is_empty then end end end convertmus (musdata: MANAGED_POINTER; len: INTEGER_32; filename: STRING_8) local mus2mid: MUS2MID do create mus2mid.make (musdata) mus2mid.fill_output if not i_main.M_misc.m_writefile_list (filename, mus2mid.output) then print ("Error writing midi file " + filename) end end stopsong -- Stop playing the current song. do if music_initialized then if {SDL_MIXER_FUNCTIONS_API}.mix_halt_music /= 0 then {I_MAIN}.i_error ("Could not Mix_HaltMusic") end end end resumemusic -- Un-pause music do if music_initialized then musicpaused := False updatemusicvolume end end updatemusicvolume -- SDL_mixer's native MIDI music playing does not pause properly. -- As a workaround, set the volume to 0 when paused local vol: INTEGER_32 do if musicpaused then vol := 0 else vol := ((current_music_volume.to_integer_64 * {MIX}.mix_max_volume) // 127).to_integer_32 end vol := {SDL_MIXER_FUNCTIONS_API}.mix_volume_music (vol) end unregistersong (handle: detachable MIX_MUSIC_STRUCT_API) -- Un-register (free) song data do if music_initialized then if attached handle as h then {SDL_MIXER_FUNCTIONS_API}.mix_free_music (h) end end end shutdown -- Shutdown the music subsystem do if music_initialized then if {SDL_MIXER_FUNCTIONS_API}.mix_halt_music /= 0 then {I_MAIN}.i_error ("Could not Mix_HaltMusic") end music_initialized := False if sdl_was_initialized then {SDL_MIXER_FUNCTIONS_API}.mix_close_audio {SDL_FUNCTIONS_API}.sdl_quit_sub_system ({SDL_CONSTANT_API}.sdl_init_audio.to_natural_32) sdl_was_initialized := False end end end set_music_volume (vol: INTEGER_32) -- Set music volume - range 0-127 do current_music_volume := vol updatemusicvolume end pause_music -- Pause music do if music_initialized then musicpaused := True updatemusicvolume end end music_is_playing: BOOLEAN -- Query if music is playing. do if music_initialized then Result := {MIX}.mix_playing_music end end end -- class MUSIC_SDL_MODULE
Generated by ISE EiffelStudio