Property definitions

android $ MediaPlayer :: defaultinit
# Used to play sounds, designed to use with medium sized sounds or streams
# The Android MediaPlayer has a complex state diagram that you'll need to
# respect if you want your MediaPlayer to work fine, see the android doc
class MediaPlayer
	private var nmedia_player: NativeMediaPlayer is noinit

	# Used to control the state of the mediaplayer
	private var is_prepared = false is writable

	# The sound associated with this mediaplayer
	var sound: nullable Music = null is writable

	# Error gestion
	var error: nullable Error = null

	# Create a new MediaPlayer, but no sound is attached, you'll need
	# to use `load_sound` before using it
	init do self.nmedia_player = (new NativeMediaPlayer).new_global_ref

	# Init the mediaplayer with a sound resource id
	init from_id(context: NativeActivity, id: Int) do
		self.nmedia_player = new NativeMediaPlayer.create(context, id)
		if self.nmedia_player.is_java_null then
			self.error = new Error("Failed to create the MediaPlayer")
			self.sound = new Music.priv_init(id, self, self.error)
		end
		self.sound = new Music.priv_init(id, self, null)
	end

	# Load a sound for a given resource id
	fun load_sound(id: Int, context: NativeActivity): Music do
		# FIXME: maybe find a better way to handle this situation
		# If two different music are loaded with the same `MediaPlayer`,
		# a new `NativeMediaPlayer` will be created for the secondd music
		# and the nit program will loose the handle to the previous one
		# If the previous music is playing, we need to stop it
		if playing then
			stop
			reset
			destroy
		end

		self.nmedia_player = new NativeMediaPlayer.create(context, id)
		if self.nmedia_player.is_java_null then
			self.error = new Error("Failed to load a sound")
			self.sound = new Music.priv_init(id, self, new Error("Sound loading failed"))
			return self.sound.as(not null)
		else
			if self.error != null then self.error = null
			self.sound = new Music.priv_init(id, self, null)
			self.is_prepared = true
			return self.sound.as(not null)
		end
	end

	# Starts or resumes playback
	# REQUIRE `self.sound != null`
	fun start do
		if self.error != null then return
		if not is_prepared then prepare
		nmedia_player.start
	end

	# Stops playback after playback has been stopped or paused
	# REQUIRE `self.sound != null`
	fun stop do
		if self.error != null then return
		is_prepared = false
		nmedia_player.stop
	end

	# Prepares the player for playback, synchronously
	# REQUIRE `self.sound != null`
	fun prepare do
		if self.error != null then return
		assert sound != null
		nmedia_player.prepare
		is_prepared = true
	end

	# Pauses playback
	# REQUIRE `self.sound != null`
	fun pause do
		if self.error != null then return
		assert sound != null
		nmedia_player.pause
	end

	# Checks whether the mediaplayer is playing
	fun playing: Bool do return nmedia_player.playing

	# Releases the resources associated with this MediaPlayer
	fun destroy do
		nmedia_player.release
		self.sound = null
	end

	# Reset MediaPlayer to its initial state
	fun reset do nmedia_player.reset

	# Sets the datasource (file-path or http/rtsp URL) to use
	fun data_source(path: String): Music do
		sys.jni_env.push_local_frame(1)
		var retval = nmedia_player.data_source_path(path.to_java_string)
		sys.jni_env.pop_local_frame
		if retval == 0 then
			self.error = new Error("could not load the sound " + path)
			self.sound = new Music.priv_init(null, self, self.error)

		else
			self.sound = new Music.priv_init(null, self, null)
		end
		return self.sound.as(not null)
	end
	# Sets the data source (NativeFileDescriptor) to use
	fun data_source_fd(fd: NativeAssetFileDescriptor): Music do
		if not fd.is_java_null then
			if nmedia_player.data_source_fd(fd.file_descriptor, fd.start_offset, fd.length) == 0 then
				self.error = new Error("could not load the sound")
				self.sound = new Music.priv_init(null, self, self.error)
			else
				self.sound = new Music.priv_init(null, self, null)
			end
			return self.sound.as(not null)
		else
			var error = new Error("could not load the sound")
			return new Music.priv_init(null, self, error)
		end
	end

	# Checks whether the MediaPlayer is looping or non-looping
	fun looping: Bool do return nmedia_player.looping

	# Sets the player to be looping or non-looping
	fun looping=(b: Bool) do nmedia_player.looping = b

	# Sets the volume on this player
	fun volume=(volume: Float) do nmedia_player.volume = volume

	# Sets the left volume and the right volume of this player
	fun both_volume(left_volume, right_volume: Float) do nmedia_player.both_volume(left_volume, right_volume)

	# Sets the audio stream type for this media player
	fun stream_type=(stream_type: Int) do nmedia_player.stream_type = stream_type
end
lib/android/audio.nit:364,1--508,3