class EL_AUDIO_OUTPUT_DEVICE

(source code)

Description

Audio output device

note
	description: "Audio output device"

	author: "Finnian Reilly"
	copyright: "Copyright (c) 2001-2022 Finnian Reilly"
	contact: "finnian at eiffel hyphen loop dot com"

	license: "MIT license (See: en.wikipedia.org/wiki/MIT_License)"
	date: "2023-07-03 8:03:23 GMT (Monday 3rd July 2023)"
	revision: "6"

class
	EL_AUDIO_OUTPUT_DEVICE

inherit
	EL_MULTIMEDIA_SYSTEM_C_API
		undefine
			io
		end

	EL_MODULE_LIO

create
	make_open

feature {NONE} -- Initialization

	make_open (wave_header: EL_AUDIO_WAVE_HEADER)
			--
		local
			status: INTEGER
		do
			create waveform_format.make (wave_header)
			create device_handle.make (c_size_of_HWAVEOUT)
			status := c_wave_out_open (
				device_handle.item,
				cdef_WAVE_MAPPER,
				waveform_format.self_ptr,
				c_wave_out_procedure,
				Default_pointer,
				cdef_CALLBACK_FUNCTION
			)
			is_open := status = cdef_MMSYSERR_NOERROR
		ensure
			is_open: is_open
		end

feature -- Status query

	is_paused: BOOLEAN

	is_open: BOOLEAN

	is_volume_setting_saved: BOOLEAN

feature -- Basic operations

	pause
			--
		local
			status: INTEGER
		do
			status := c_wave_out_pause (device_handle.item)
			is_paused := status = cdef_MMSYSERR_NOERROR
			check
				is_paused: is_paused
			end
		end

	restart
			--
		local
			status: INTEGER
		do
			status := c_wave_out_restart (device_handle.item)
			check
				is_restarted: is_paused implies status = cdef_MMSYSERR_NOERROR
			end
			is_paused := false
		end

	reset
			--
		local
			status: INTEGER
		do
			status := c_wave_out_reset (device_handle.item)
			check
				is_reset: status = cdef_MMSYSERR_NOERROR
			end
		end

	close
			--
		local
			status: INTEGER
		do

			from status := cdef_WAVERR_STILLPLAYING until status /= cdef_WAVERR_STILLPLAYING loop
				status := c_wave_out_close (device_handle.item)
				if status = cdef_WAVERR_STILLPLAYING then
					reset
				end
			end
			check
				is_closed: status = cdef_MMSYSERR_NOERROR
			end
		end

	save_volume_setting
			--
		local
			status: INTEGER
		do
			status := c_get_volume (device_handle.item, $volume_setting)
			is_volume_setting_saved := status = cdef_MMSYSERR_NOERROR
		end

	restore_volume_setting
			--
		require
			volume_setting_saved: is_volume_setting_saved
		local
			status: INTEGER
		do
			if is_volume_setting_saved then
				status := c_set_volume (device_handle.item, volume_setting)
				check
					volume_set: status = cdef_MMSYSERR_NOERROR
				end
			end
		end

	set_volume_as_percentage (channel_volume_percent: ARRAY [INTEGER])
			--
		local
			status, ch, volume_word, combined_volume_word: INTEGER
		do
			from ch := 1 until ch > channel_volume_percent.count loop
				volume_word := (Maximum_volume * (channel_volume_percent [ch] / 100)).rounded
				volume_word := volume_word.bit_shift_left (16 * (ch - 1))
				combined_volume_word := combined_volume_word + volume_word
				ch := ch + 1
			end
			status := c_set_volume (device_handle.item, combined_volume_word)
			check
				volume_set: status = cdef_MMSYSERR_NOERROR
			end
		end

feature -- Access

	device_handle: MANAGED_POINTER

	buffers_played_count: INTEGER
			--
		do
			Result := c_buffers_played_count
		end

feature {NONE} -- Implementation

	waveform_format: EL_WAVEFORM_FORMAT

	volume_setting: INTEGER

feature -- Constants

	Maximum_volume: INTEGER = 0xFFFF

invariant

	valid_wave_out_handle: device_handle /= Void

end