diff options
Diffstat (limited to 'src/voice/audio.rs')
| -rw-r--r-- | src/voice/audio.rs | 84 |
1 files changed, 83 insertions, 1 deletions
diff --git a/src/voice/audio.rs b/src/voice/audio.rs index 8a001d1..cb60f57 100644 --- a/src/voice/audio.rs +++ b/src/voice/audio.rs @@ -1,5 +1,6 @@ use parking_lot::Mutex; use std::sync::Arc; +use std::time::Duration; pub const HEADER_LEN: usize = 12; pub const SAMPLE_RATE: u32 = 48_000; @@ -36,12 +37,63 @@ pub enum AudioType { /// Control object for audio playback. /// /// Accessed by both commands and the playback code -- as such, access is -/// always guarded. +/// always guarded. In particular, you should expect to receive +/// a [`LockedAudio`] when calling [`Handler::play_returning`] or +/// [`Handler::play_only`]. +/// +/// # Example +/// +/// ```rust,ignore +/// use serenity::voice::{Handler, LockedAudio, ffmpeg}; +/// +/// let handler: Handler = /* ... */; +/// let source = ffmpeg("../audio/my-favourite-song.mp3")?; +/// let safe_audio: LockedAudio = handler.play_only(); +/// { +/// let audio_lock = safe_audio_control.clone(); +/// let mut audio = audio_lock.lock(); +/// +/// audio.volume(0.5); +/// } +/// ``` +/// +/// [`LockedAudio`]: type.LockedAudio.html +/// [`Handler::play_only`]: struct.Handler.html#method.play_only +/// [`Handler::play_returning`]: struct.Handler.html#method.play_returning pub struct Audio { + + /// Whether or not this sound is currently playing. + /// + /// Can be controlled with [`play`] or [`pause`] + /// if chaining is desired. + /// + /// [`play`]: #method.play + /// [`pause`]: #method.pause pub playing: bool, + + /// The desired volume for playback. + /// + /// Sensible values fall between `0.0` and `1.0`. + /// Can be controlled with [`volume`] if chaining is desired. + /// + /// [`volume`]: #method.volume pub volume: f32, + + /// Whether or not the sound has finished, or reached the end of its stream. + /// + /// ***Read-only*** for now. pub finished: bool, + + /// Underlying data access object. + /// + /// *Calling code is not expected to use this.* pub source: Box<AudioSource>, + + /// The current position for playback. + /// + /// Consider the position fields **read-only** for now. + pub position: Duration, + pub position_modified: bool, } impl Audio { @@ -51,26 +103,56 @@ impl Audio { volume: 1.0, finished: false, source, + position: Duration::new(0, 0), + position_modified: false, } } + /// Sets [`playing`] to `true` in a manner that allows method chaining. + /// + /// [`playing`]: #structfield.playing pub fn play(&mut self) -> &mut Self { self.playing = true; self } + /// Sets [`playing`] to `false` in a manner that allows method chaining. + /// + /// [`playing`]: #structfield.playing pub fn pause(&mut self) -> &mut Self { self.playing = false; self } + /// Sets [`volume`] in a manner that allows method chaining. + /// + /// [`volume`]: #structfield.volume pub fn volume(&mut self, volume: f32) -> &mut Self { self.volume = volume; self } + + /// Change the position in the stream for subsequent playback. + /// + /// Currently a No-op. + pub fn position(&mut self, position: Duration) -> &mut Self { + self.position = position; + self.position_modified = true; + + self + } + + /// Steps playback location forward by one frame. + /// + /// *Used internally*, although in future this might affect seek position. + pub(crate) fn step_frame(&mut self) { + self.position += Duration::from_millis(20); + self.position_modified = false; + } + } /// Threadsafe form of an instance of the [`Audio`] struct, locked behind a |