1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
//! An interface for controlling instances of sounds and arrangements.

use std::sync::Arc;

use atomic::{Atomic, Ordering};

use crate::{
	command::{
		producer::{CommandError, CommandProducer},
		InstanceCommand,
	},
	Value,
};

use super::{
	InstanceId, InstanceState, PauseInstanceSettings, ResumeInstanceSettings, StopInstanceSettings,
};

#[derive(Debug, Clone)]
/// Allows you to control an instance of a sound or arrangement.
pub struct InstanceHandle {
	id: InstanceId,
	state: Arc<Atomic<InstanceState>>,
	position: Arc<Atomic<f64>>,
	command_producer: CommandProducer,
}

impl InstanceHandle {
	pub(crate) fn new(
		id: InstanceId,
		state: Arc<Atomic<InstanceState>>,
		position: Arc<Atomic<f64>>,
		command_producer: CommandProducer,
	) -> Self {
		Self {
			id,
			state,
			position,
			command_producer,
		}
	}

	/// Returns the ID of the instance.
	pub fn id(&self) -> InstanceId {
		self.id
	}

	/// Returns the playback state of the instance.
	pub fn state(&self) -> InstanceState {
		self.state.load(Ordering::Relaxed)
	}

	/// Returns the playback position of the instance.
	pub fn position(&self) -> f64 {
		self.position.load(Ordering::Relaxed)
	}

	/// Sets the volume of the instance.
	pub fn set_volume(&mut self, volume: impl Into<Value<f64>>) -> Result<(), CommandError> {
		self.command_producer
			.push(InstanceCommand::SetInstanceVolume(self.id, volume.into()).into())
	}

	/// Sets the playback rate of the instance.
	pub fn set_playback_rate(
		&mut self,
		playback_rate: impl Into<Value<f64>>,
	) -> Result<(), CommandError> {
		self.command_producer
			.push(InstanceCommand::SetInstancePlaybackRate(self.id, playback_rate.into()).into())
	}

	/// Sets the panning of the instance.
	pub fn set_panning(&mut self, panning: impl Into<Value<f64>>) -> Result<(), CommandError> {
		self.command_producer
			.push(InstanceCommand::SetInstancePanning(self.id, panning.into()).into())
	}

	/// Offsets the playback position of the instance by the specified amount (in seconds).
	pub fn seek(&mut self, offset: f64) -> Result<(), CommandError> {
		self.command_producer
			.push(InstanceCommand::SeekInstance(self.id, offset).into())
	}

	/// Sets the playback position of the instance to the specified time (in seconds).
	pub fn seek_to(&mut self, position: f64) -> Result<(), CommandError> {
		self.command_producer
			.push(InstanceCommand::SeekInstanceTo(self.id, position).into())
	}

	/// Pauses the instance.
	pub fn pause(&mut self, settings: PauseInstanceSettings) -> Result<(), CommandError> {
		self.command_producer
			.push(InstanceCommand::PauseInstance(self.id, settings).into())
	}

	/// Resumes the instance.
	pub fn resume(&mut self, settings: ResumeInstanceSettings) -> Result<(), CommandError> {
		self.command_producer
			.push(InstanceCommand::ResumeInstance(self.id, settings).into())
	}

	/// Stops the instance.
	pub fn stop(&mut self, settings: StopInstanceSettings) -> Result<(), CommandError> {
		self.command_producer
			.push(InstanceCommand::StopInstance(self.id, settings).into())
	}
}