From 0c16a2050ad6f899f803cec895542a39ff84bfd4 Mon Sep 17 00:00:00 2001 From: Anatoly Bazarov Date: Sat, 23 Sep 2023 15:56:18 -0400 Subject: [PATCH] replace darkice with pulseaudio, remove fade and mixer, update rust and ubuntu docker versions --- README.md | 32 +------------------------------- docker/ircbot/index.js | 14 ++++++++++---- docker/streamer/Dockerfile | 2 +- docker/streamer/entrypoint.sh | 11 +---------- docker/streamer/keepalive.sh | 2 +- etc/pulse.liq | 2 +- src/announce.rs | 6 ++---- src/main.rs | 14 +++++--------- src/mixer.rs | 33 --------------------------------- src/rest.rs | 30 +++--------------------------- 10 files changed, 25 insertions(+), 121 deletions(-) delete mode 100644 src/mixer.rs diff --git a/README.md b/README.md index 4062ebd..f07fc03 100644 --- a/README.md +++ b/README.md @@ -212,36 +212,6 @@ all above return (example): } ``` -### `GET /mixer/music/fade?start=&end=&duration=` -`START` is the volume percentage to start the fade at, e.g. `100` - -`END` is the volume percentage to end the fade at, e.g. `50` - -`DURATION` is the duration, in milliseconds, over which to conduct the fade, e.g. `3000` - -it returns: -``` -{ - "done": true -} -``` - -### `GET /mixer/announce/volume?vol=` -`VOLUME` is the volume to set the announcements to, examples of acceptable values are - -`120%` - will set the volume to 120% - -`+10%` - this will increase the volume by 10% - -`140` - this will set the volume to 140dB - -it returns: -``` -{ - "volume": -} -``` - ### `GET /espeak?text=` ### `GET /elevenlabs?text=` this will use espeak, or the elevenlabs API to speak your `TEXT` @@ -251,4 +221,4 @@ it will return: { "text": } -``` \ No newline at end of file +``` diff --git a/docker/ircbot/index.js b/docker/ircbot/index.js index 7f953c8..7a37c41 100644 --- a/docker/ircbot/index.js +++ b/docker/ircbot/index.js @@ -9,11 +9,12 @@ var radioBase = 'http://icecast2:8000'; let configData = fs.readFileSync('/etc/ircbot.json'); let config = JSON.parse(configData); - bot.connect({ host: config.server, port: config.port, - nick: config.nick + nick: config.nick, + ssl: config.port == 6697 ? true : false, + rejectUnauthorized: false }); bot.on('registered', function() { @@ -22,6 +23,10 @@ bot.on('registered', function() { }); }); +bot.on('debug', function(event) { + console.log(event); +}); + bot.on('message', function(event) { var args = event.message.split(' '); var text = args.slice(1).join(' '); @@ -35,13 +40,12 @@ bot.on('message', function(event) { }); } - if (event.message.match(/^!skip/)) { + if (event.message.match(/^!skip/)) { spotifyApi('/skip', event, data => { return _nowPlaying(data, event); }); } - if (event.message.match(/^!np/)) { return _nowPlaying(false, event); } @@ -82,6 +86,8 @@ function _nowPlaying(data, event){ if(data) return event.reply(makeSpotifyMessage(data, listeners)); spotifyApi("/np", event, data => { + console.log("sending reply with"); + console.log(data); event.reply(makeSpotifyMessage(data, listeners)); }); }); diff --git a/docker/streamer/Dockerfile b/docker/streamer/Dockerfile index ab3a49b..79e30b3 100644 --- a/docker/streamer/Dockerfile +++ b/docker/streamer/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:20.04 +FROM ubuntu:22.04 RUN apt-get update && apt-get -y install pulseaudio alsa-utils liquidsoap curl sox espeak diff --git a/docker/streamer/entrypoint.sh b/docker/streamer/entrypoint.sh index faee237..178d8ce 100644 --- a/docker/streamer/entrypoint.sh +++ b/docker/streamer/entrypoint.sh @@ -6,15 +6,6 @@ echo "Starting pulseaudio ..." pulseaudio -D --exit-idle-time=-1 sleep 2 -pactl load-module module-null-sink sink_name=spotifm_music sink_properties=device.description=spotifm_music -pactl load-module module-null-sink sink_name=spotifm_announce sink_properties=device.description=spotifm_announce -pactl load-module module-null-sink sink_name=spotifm_master sink_properties=device.description=spotifm_master -sleep 1 -pactl load-module module-loopback source=spotifm_music.monitor sink=spotifm_master -pactl load-module module-loopback source=spotifm_announce.monitor sink=spotifm_master - -pactl set-default-source spotifm_master.monitor - echo "Starting liquidsoap ..." liquidsoap /etc/liquidsoap/pulse.liq --daemon sleep 2 @@ -23,5 +14,5 @@ echo "Starting keepalive ..." /keepalive.sh & echo "Starting spotifm ..." -PULSE_SINK=spotifm_music spotifm /etc/spotifm.json +spotifm /etc/spotifm.json \ No newline at end of file diff --git a/docker/streamer/keepalive.sh b/docker/streamer/keepalive.sh index b53a669..c7c0baf 100644 --- a/docker/streamer/keepalive.sh +++ b/docker/streamer/keepalive.sh @@ -2,7 +2,7 @@ # if more than 5 seconds of silence, send SIGALRM to spotifm so it renews the session while true; do - PULSE_SOURCE=spotifm_music.monitor sox -d -n silence 1 1 0% 1 15.0 0% + PULSE_SOURCE=auto_null.monitor sox -d -n silence 1 1 0% 1 15.0 0% pkill -SIGALRM spotifm touch /tmp/silence_$(date +%s) sleep 5 diff --git a/etc/pulse.liq b/etc/pulse.liq index 1400dad..8ddc415 100644 --- a/etc/pulse.liq +++ b/etc/pulse.liq @@ -1,6 +1,6 @@ # Define the PulseAudio input input = input.pulseaudio( - device="spotifm_master.monitor" + device="auto_null.monitor" ) # Define the Icecast2 output diff --git a/src/announce.rs b/src/announce.rs index d1cc590..62ca03e 100644 --- a/src/announce.rs +++ b/src/announce.rs @@ -1,6 +1,6 @@ -use std::process::{Command}; +use std::process::Command; use std::sync::{Arc, Mutex}; -use crate::db::{SpotifyTrack}; +use crate::db::SpotifyTrack; use crate::config::{SpotifmConfig, SpotifmEspeakCfg, SpotifmElevenLabsCfg}; pub fn announcements(_config: Arc>, track: &SpotifyTrack, tracks_played: usize) { @@ -24,7 +24,6 @@ pub fn announcements(_config: Arc>, track: &SpotifyTrack, t pub fn espeak(text: String, config: SpotifmEspeakCfg){ Command::new("espeak") - .env("PULSE_SINK", "spotifm_announce") .arg("-s") .arg(config.speed.to_string()) .arg("-a") @@ -51,7 +50,6 @@ pub fn get_elevenlabs_tts(text: &str, config: SpotifmElevenLabsCfg) { pub fn play_elevenlabs(){ Command::new("mplayer") - .env("PULSE_SINK", "spotifm_announce") .arg("/tmp/output.mp3") .output() .unwrap(); diff --git a/src/main.rs b/src/main.rs index cc0beff..a126d29 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,7 +9,7 @@ use librespot::core::config::SessionConfig; use librespot::core::session::Session; use librespot::playback::audio_backend; use librespot::playback::config::{AudioFormat, PlayerConfig}; -use librespot::playback::mixer::{NoOpVolume}; +use librespot::playback::mixer::NoOpVolume; use librespot::playback::player::{Player,PlayerEvent}; mod db; @@ -17,7 +17,6 @@ mod rest; mod signals; mod config; mod announce; -mod mixer; use config::SpotifmConfig; @@ -28,7 +27,6 @@ async fn main() { let mut tracks_played = 0; - // get the first argument let args: Vec = std::env::args().collect(); let db = db::SpotifyDatabase::new(); @@ -42,19 +40,17 @@ async fn main() { rest::start(rest_tx.clone(), config.clone(), session.clone(), db.clone()); db::populate(config.lock().unwrap().uris.clone(), session.clone(), db.clone()); - eprintln!("waiting for playlist..."); + eprintln!("Waiting for playlist..."); // wait until at least one track in playlist while db.len() == 0 { thread::sleep(time::Duration::from_millis(10)); } - eprintln!("playlist ready, starting playback..."); + eprintln!("Playlist partially loaded, starting playback..."); 'track_list: loop { - tracks_played += 1; - db.advance_track(); match db.current_track() { @@ -73,7 +69,7 @@ async fn main() { player.load(track.spotify_id(), true, 0); match db.next_track() { - Err(err) => eprintln!("preload error: {}", err), + Err(err) => eprintln!("Preload error: {}", err), Ok(track) => player.preload(track.spotify_id()), } @@ -133,7 +129,7 @@ pub async fn create_session(config: &Arc>) -> Session { let credentials = Credentials::with_password(config.user.clone(), config.pass.clone()); let (session, _) = Session::connect(session_config, credentials, None, false).await - .map_err(|err| { panic!("{}", err.to_string())} ) + .map_err(|err| { eprintln!("Error creating session: {}", err.to_string())} ) .unwrap(); return session; diff --git a/src/mixer.rs b/src/mixer.rs deleted file mode 100644 index 8f6f1da..0000000 --- a/src/mixer.rs +++ /dev/null @@ -1,33 +0,0 @@ -use std::process::{Command}; -use std::thread; -use std::time::{Duration, Instant}; - -pub fn volume_fade(start: u32, end: u32, duration: u64) { - let start_time = Instant::now(); - let total_duration = Duration::from_millis(duration); - - while Instant::now() - start_time < total_duration { - let elapsed = Instant::now() - start_time; - let progress = elapsed.as_millis() as f64 / duration as f64; - let current_value = (start as f64 + (end as f64 - start as f64) * progress) as u32; - - Command::new("pactl") - .arg("set-sink-volume") - .arg("spotifm_music") - .arg(format!("{}%", current_value)) - .output() - .unwrap(); - - let sleep_duration = total_duration / 100; - thread::sleep(sleep_duration); - } -} - -pub fn announce_volume(volume: String){ - Command::new("pactl") - .arg("set-sink-volume") - .arg("spotifm_announce") - .arg(volume) - .output() - .unwrap(); -} \ No newline at end of file diff --git a/src/rest.rs b/src/rest.rs index 65885fc..610fa84 100644 --- a/src/rest.rs +++ b/src/rest.rs @@ -20,9 +20,8 @@ use std::iter::FromIterator; use std::{sync::mpsc::SyncSender, thread}; use crate::db::{SpotifyDatabase, SpotifyTrack}; -use crate::config::{SpotifmConfig}; +use crate::config::SpotifmConfig; use crate::announce::{espeak, get_elevenlabs_tts, play_elevenlabs}; -use crate::mixer::{volume_fade, announce_volume}; const CLIENT_ID: &str = "65b708073fc0480ea92a077233ca87bd"; const SCOPES: &str = @@ -50,27 +49,6 @@ pub struct AnnounceSong { pub gap: Option, } -#[get("/mixer/music/fade")] -pub async fn set_mixer_music_fade( - req: HttpRequest -) -> HttpResponse { - let query = web::Query::>::from_query(req.query_string()).unwrap(); - let start = query.get("start").unwrap().parse::().unwrap(); - let end = query.get("end").unwrap().parse::().unwrap(); - let duration = query.get("duration").unwrap().parse::().unwrap(); - volume_fade(start, end, duration); - return HttpResponse::Ok().json(HashMap::from([("done", true)])); -} - -#[get("/mixer/announce/volume")] -pub async fn set_mixer_announce_volume( - req: HttpRequest -) -> HttpResponse { - let query = web::Query::>::from_query(req.query_string()).unwrap(); - announce_volume(query.get("vol").unwrap().clone()); - return HttpResponse::Ok().json(HashMap::from([("volume", query.get("vol").unwrap())])); -} - #[get("/elevenlabs")] pub async fn do_elevenlabs_say( req: HttpRequest, @@ -87,7 +65,7 @@ pub async fn do_elevenlabs_say( } #[get("/espeak")] -pub async fn do_announce_say( +pub async fn do_espeak_say( req: HttpRequest, config: Data>>, ) -> HttpResponse { @@ -457,10 +435,8 @@ pub async fn start(tx: SyncSender, config: Arc .service(search) .service(show_playlist) .service(shuffle) - .service(set_mixer_music_fade) - .service(set_mixer_announce_volume) .service(get_announce) - .service(do_announce_say) + .service(do_espeak_say) .service(do_elevenlabs_say) .service(edit_announce_song) .service(edit_announce_bumper)