From 324a288fbb0dd7d135aa9aab876cf39dabb6a02e Mon Sep 17 00:00:00 2001 From: Kyle Simpson Date: Wed, 31 Jan 2018 19:12:56 +0000 Subject: Multiple audio stream playback, volume control, pausing * Fix Speaking state, use latest voice API version * Speaking state would remain stuck on after playing particularly long stretches of audio. So far as I can tell, playing 5 frames of silence BEFORE changing the state seems to do the trick. * Added new constant to make sure the library uses v3 of the voice api, which it is written for. * Heartbeat interval adjusted by * .75 as recommended by Discord. * Initial version of new Audio wrapper. * Single audio file case, as before.. * Loop over all available audio samples. * Combine audio streams, account for volume. * Cheaper explicit Opus silence frames. As per Discord's recommendation, use a well-known 3-byte silence frame when needed. * A bit of cleanup Cleanup some of the code, rename some short-form fields to longer forms (e.g. `s/src/source`), and remove a breaking change. `Handler::play` was changed to return `LockedAudio` instead of `()`. If someone were to rely on `Handler::play` returning `()`, the return type change would break their code. Instead, this functionality has been added to a new `Handler::play_returning` function. --- src/voice/handler.rs | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) (limited to 'src/voice/handler.rs') diff --git a/src/voice/handler.rs b/src/voice/handler.rs index c3a5f05..8113d94 100644 --- a/src/voice/handler.rs +++ b/src/voice/handler.rs @@ -2,9 +2,11 @@ use constants::VoiceOpCode; use gateway::InterMessage; use model::id::{ChannelId, GuildId, UserId}; use model::voice::VoiceState; +use parking_lot::Mutex; +use std::sync::Arc; use std::sync::mpsc::{self, Sender as MpscSender}; use super::connection_info::ConnectionInfo; -use super::{AudioReceiver, AudioSource, Status as VoiceStatus, threading}; +use super::{Audio, AudioReceiver, AudioSource, Status as VoiceStatus, threading, LockedAudio}; /// The handler is responsible for "handling" a single voice connection, acting /// as a clean API above the inner connection. @@ -249,13 +251,35 @@ impl Handler { } } - /// Plays audio from a source. This can be a source created via - /// [`voice::ffmpeg`] or [`voice::ytdl`]. + /// Plays audio from a source. + /// + /// This can be a source created via [`voice::ffmpeg`] or [`voice::ytdl`]. /// /// [`voice::ffmpeg`]: fn.ffmpeg.html /// [`voice::ytdl`]: fn.ytdl.html pub fn play(&mut self, source: Box) { - self.send(VoiceStatus::SetSender(Some(source))) + self.play_returning(source); + } + + /// Plays audio from a source, returning the locked audio source. + pub fn play_returning(&mut self, source: Box) -> LockedAudio { + let player = Arc::new(Mutex::new(Audio::new(source))); + self.send(VoiceStatus::AddSender(player.clone())); + + player + } + + /// Plays audio from a source. + /// + /// Unlike `play`, this stops all other sources attached + /// to the channel. + /// + /// [`play`]: #method.play + pub fn play_only(&mut self, source: Box) -> LockedAudio { + let player = Arc::new(Mutex::new(Audio::new(source))); + self.send(VoiceStatus::SetSender(Some(player.clone()))); + + player } /// Stops playing audio from a source, if one is set. -- cgit v1.2.3