Skip to content

Commit

Permalink
feat: add symponia codecs
Browse files Browse the repository at this point in the history
  • Loading branch information
Phosphorus-M committed Mar 28, 2024
1 parent 2913ab1 commit 8b34f25
Show file tree
Hide file tree
Showing 9 changed files with 144 additions and 46 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/target
Secrets*.toml
.vscode
*.dca
97 changes: 94 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ readme = "README.md"
anyhow = "1.0.66"
shuttle-serenity = "0.42.0"
shuttle-runtime = "0.42.0"
serenity = { version = "0.12.1", default-features = true, features = ["cache", "framework", "client", "gateway", "rustls_backend", "model", "standard_framework", "voice"] }
serenity = { version = "=0.12.0", default-features = true, features = ["cache", "framework", "client", "gateway", "rustls_backend", "model", "standard_framework", "voice"] }
#shuttle-secrets = "0.42.0"
tokio = "1.26.0"
tracing = "0.1.37"
Expand All @@ -23,7 +23,8 @@ reqwest = { version = "0.12.2", features = ["json"] }
scraper = { version = "0.19.0", features = ["indexmap", "deterministic", "atomic"] }
plantita_welcomes = { git = "https://github.com/CrawKatt/plantita_welcomes.git" }
image = "0.24.7"
symphonia = { version = "0.5.3", default-features = false, features = ["mp3", "ogg", "wav"] }

[dependencies.parking_lot]
version = "0.12"
features = ["send_guard"]
features = ["send_guard"]
61 changes: 29 additions & 32 deletions src/config/setup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use anyhow::anyhow;
use shuttle_runtime::SecretStore;
use songbird::driver::Bitrate;
use songbird::SerenityInit;
use songbird::input::cached::{Memory, Compressed};
use songbird::input::cached::Compressed;
use songbird::input::File;
use serenity::prelude::*;
use serenity::framework::{StandardFramework, standard::macros::hook};
Expand Down Expand Up @@ -66,50 +66,47 @@ pub async fn setup( secret_store: SecretStore, public_folder: PathBuf) -> Result
// Loading the audio ahead of time.
let mut audio_map = HashMap::new();

// Creation of an in-memory source.
//
// This is a small sound effect, so storing the whole thing is relatively cheap.
//
// `spawn_loader` creates a new thread which works to copy all the audio into memory
// ahead of time. We do this in both cases to ensure optimal performance for the audio
// core.
let src = public_folder.clone().join("ting.wav");
let file = File::new(src);
let ting_src = Memory::new(
file.into())
.await
.unwrap_or_else(|_| panic!("File should be in root folder. {}", public_folder.clone().join("ting.wav").as_path().to_str().unwrap_or_default()));
let _ = ting_src.raw.spawn_loader();
audio_map.insert("ting".into(), CachedSound::Uncompressed(ting_src));
load_sound_file(&mut audio_map, &public_folder, "loop", "loop.mp3").await;
load_sound_file(&mut audio_map, &public_folder, "ting", "ting.mp3").await;
load_sound_file(&mut audio_map, &public_folder, "song", "Cloudkicker_-_Loops_-_22_2011_07.mp3").await;

// Another short sting, to show where each loop occurs.
let src = public_folder.clone().join("loop.wav");
let file = File::new(src);
let loop_src = Memory::new(
file.into())
.await
.expect("File should be in root folder.");

let _ = loop_src.raw.spawn_loader();
audio_map.insert("loop".into(), CachedSound::Uncompressed(loop_src));
data.insert::<SoundStore>(Arc::new(Mutex::new(audio_map)));
}

// Creation of a compressed source.
Ok(client)
}


async fn load_sound_file(audio_map: &mut HashMap<String, CachedSound>, public_folder: &PathBuf, sound: &str, song_file: &str) {
// Creation of a compressed source.
//
// This is a full song, making this a much less memory-heavy choice.
//
// Music by Cloudkicker, used under CC BY-SC-SA 3.0 (https://creativecommons.org/licenses/by-nc-sa/3.0/).
let src = public_folder.clone().join("Cloudkicker_-_Loops_-_22_2011_07.mp3");
let src = public_folder.clone().join(song_file);
let file = File::new(src);
let song_src = Compressed::new(
file.into(),
Bitrate::BitsPerSecond(128_000)).await.expect("Link may be dead.");
Bitrate::Auto,
)
.await
.expect("These parameters are well-defined.");
let _ = song_src.raw.spawn_loader();
audio_map.insert("song".into(), CachedSound::Compressed(song_src));

data.insert::<SoundStore>(Arc::new(Mutex::new(audio_map)));
}
// Compressed sources are internally stored as DCA1 format files.
// Because `Compressed` implements `std::io::Read`, we can save these
// to disk and use them again later if we want!
let mut creator = song_src.new_handle();

let song_file_compressed = song_file.replace("mp3", "dca");

std::thread::spawn(move || {
let mut out_file = std::fs::File::create(&song_file_compressed).unwrap();
std::io::copy(&mut creator, &mut out_file).expect("Error writing out song!");
});

Ok(client)
audio_map.insert(sound.into(), CachedSound::Compressed(song_src));
}


Expand Down
26 changes: 17 additions & 9 deletions src/general_commands/songbird_commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,7 @@ use serenity::{
use serenity::all::standard::macros::command;

use songbird::{
Call,
Event,
EventContext,
EventHandler as VoiceEventHandler,
TrackEvent,
Call, Event, EventContext, EventHandler as VoiceEventHandler, TrackEvent
};

use crate::config::songbird_config::{CachedSound,SoundStore};
Expand Down Expand Up @@ -133,14 +129,19 @@ pub struct LoopPlaySound {
impl VoiceEventHandler for LoopPlaySound {
async fn act(&self, _ctx: &EventContext<'_>) -> Option<Event> {
if let Some(call_lock) = self.call_lock.upgrade() {
let src = {
let src: songbird::tracks::Track = {
let sources = self.sources.lock().await;
sources.get("loop").expect("Handle placed into cache at startup.").into()
};

let mut handler = call_lock.lock().await;
let sound = handler.play(src);
let _ = sound.set_volume(0.5);
if let Err(error) = sound.disable_loop() {
tracing::error!("Hubo un problema: {}", error);
};
}else {
println!("no se pudo");
}

None
Expand Down Expand Up @@ -206,7 +207,6 @@ pub async fn mute(ctx: &Context, msg: &Message) -> CommandResult {
pub async fn ting(ctx: &Context, msg: &Message, _args: Args) -> CommandResult {
let guild_id = msg.guild_id.unwrap();


let manager = songbird::get(ctx).await
.expect("Songbird Voice client placed in at initialisation.").clone();

Expand All @@ -215,10 +215,18 @@ pub async fn ting(ctx: &Context, msg: &Message, _args: Args) -> CommandResult {

let sources_lock = ctx.data.read().await.get::<SoundStore>().cloned().expect("Sound cache was installed at startup.");
let sources = sources_lock.lock().await;
let source = sources.get("ting").expect("Handle placed into cache at startup.");

let _sound = handler.play(source.into());
let Some(source) = sources.get("ting") else {
check_msg(msg.channel_id.say(&ctx.http, "Hubo un problema cargando el sonido!").await);
return Ok(())
};

handler.stop();

let sound = handler.play_only(source.into());

let _ = sound.set_volume(1.0);

check_msg(msg.channel_id.say(&ctx.http, "Ting!").await);
} else {
check_msg(msg.channel_id.say(&ctx.http, "Not in a voice channel to play in").await);
Expand Down
Binary file added static/loop.mp3
Binary file not shown.
Binary file removed static/loop.wav
Binary file not shown.
Binary file added static/ting.mp3
Binary file not shown.
Binary file removed static/ting.wav
Binary file not shown.

0 comments on commit 8b34f25

Please sign in to comment.