indexing description: "[ Singleton factory that creates objects of type EM_MUSIC, EM_SOUND and/or to initialize an audio stream. Use EM_SHARED_AUDIO_FACTORY to access this singleton. Whenever possible, use creation from file or from pointer. Avoid creating sound from memory except you know what you're doing. Audio format has to be the same as output settings in this case. Streaming will likely boost your CPU if you're doing a lot of other stuff the same time. ]" date: "$Date$" revision: "$Revision$" class EM_AUDIO_FACTORY inherit EM_SHARED_SUBSYSTEMS EM_SHARED_ERROR_HANDLER export {NONE} all end EM_AUDIO_CONSTANTS export {NONE} all end SDL_MIXER_FUNCTIONS_EXTERNAL export {NONE} all end SDL_RWOPS_FUNCTIONS_EXTERNAL export {NONE} all end create {EM_SHARED_AUDIO_FACTORY} make feature {NONE} -- Initialization make is -- Create new audio factory. do end feature -- Access last_music: EM_MUSIC -- Last music created last_sound: EM_SOUND -- Last sound created feature -- Music player set_player (a_command: STRING) is -- Set internal or external music player. This can be used to support more file formats. -- -- If `a_command' is an empty string, the internal player will be used (should be default). -- -- Set `a_command' to a complete command as if typed into the command line, but it should -- expect the filename to be added as last argument. -- -- Attention: This may not work on your system as sound device has to be opened twice. require a_command_not_void: a_command /= Void local c_string: EWG_ZERO_TERMINATED_STRING i: INTEGER do -- Use appropiate player (a_command = "" implies using internal player) create c_string.make_unshared_from_string (a_command) i := mix_set_music_cmd_external (c_string.item) if i /= 0 then error_handler.raise_error (error_handler.Em_error_using_audio_player, [a_command]) end end feature -- Music creation create_music_from_file (a_filename: STRING) is -- Load music file from `a_filename' into `last_music'. -- -- This can load WAVE, MOD, MIDI, OGG, MP3 and any file that can be played by a command. require a_filename_not_void: a_filename /= Void local c_string: EWG_ZERO_TERMINATED_STRING temp_music_pointer: POINTER do last_music := Void last_sound := Void create c_string.make_unshared_from_string (a_filename) temp_music_pointer := mix_load_mus_external (c_string.item) if temp_music_pointer /= default_pointer then -- We are ready for playing now. create last_music.make_from_pointer (temp_music_pointer) last_music.set_filename (a_filename) else error_handler.raise_error (error_handler.Em_error_loading_audio_file, [a_filename]) end ensure music_created: last_music /= Void end feature -- Sound creation create_sound_from_file (a_filename: STRING) is -- Load sound from file `a_filename' into `last_sound'. -- -- This can load WAVE, AIFF, RIFF, OGG, and VOC files. -- -- Attention: You must have an open mixer before using this function -- as it must know the output characteristics so it can -- convert this sample for playback. This conversion is done -- at load time. require a_filename_not_void: a_filename /= Void mixer_open: audio_subsystem.mixer.is_open local c_string_filename: EWG_ZERO_TERMINATED_STRING c_string_filemode: EWG_ZERO_TERMINATED_STRING temp_sound_pointer: POINTER do last_music := Void last_sound := Void create c_string_filename.make_unshared_from_string (a_filename) create c_string_filemode.make_unshared_from_string ("rb") temp_sound_pointer := mix_load_wav_rw_external (sdl_rwfrom_file_external (c_string_filename.item, c_string_filemode.item), 1) if temp_sound_pointer /= default_pointer then -- We are ready for playing now. create last_sound.make_from_pointer (temp_sound_pointer) last_sound.set_filename (a_filename) else error_handler.raise_error (error_handler.Em_error_loading_audio_file, [a_filename]) end ensure sound_created: last_sound /= Void end feature -- Stream creation create_stream (a_callback: EM_AUDIO_STREAM; an_argument: POINTER) is -- Create stream hook from `a_callback'. -- -- Pass in `an_argument' if you need some userdata in the callback. -- This argument will be present as `a_userdata' in later callbacks. -- -- Note: Streaming may cause your application to crash if you're doing -- a lot of CPU intensive work in parallel. require callback_not_void: a_callback /= Void mixer_open: audio_subsystem.mixer.is_open local stream_dispatcher: VOID_VOIDP_UINT8P_INT_ANONYMOUS_CALLBACK_DISPATCHER do last_music := Void last_sound := Void create stream_dispatcher.make (a_callback) mix_hook_music_external (stream_dispatcher.c_dispatcher, an_argument) ensure no_music_created: last_music = Void no_sound_created: last_sound = Void end invariant no_music_and_sound_created_at_the_same_time: not (last_music /= Void and then last_sound /= Void) end