diff --git a/Cargo.lock b/Cargo.lock index b07bc265..14d71d3e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -837,6 +837,7 @@ dependencies = [ "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "portaudio-rs 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "rodio 0.8.1 (git+https://github.com/tomaka/rodio)", + "sdl2 0.32.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1031,6 +1032,16 @@ dependencies = [ "memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "num" +version = "0.1.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", + "num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "num-bigint" version = "0.1.44" @@ -1050,6 +1061,15 @@ dependencies = [ "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "num-iter" +version = "0.1.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "num-traits" version = "0.1.43" @@ -1467,6 +1487,27 @@ name = "scopeguard" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "sdl2" +version = "0.32.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "sdl2-sys 0.32.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "sdl2-sys" +version = "0.32.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "semver" version = "0.9.0" @@ -2281,8 +2322,10 @@ dependencies = [ "checksum nix 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d37e713a259ff641624b6cb20e3b12b2952313ba36b6823c0f16e6cfd9e5de17" "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" "checksum nom 3.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05aec50c70fd288702bcd93284a8444607f3292dbdf2a30de5ea5dcdbe72287b" +"checksum num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "4703ad64153382334aa8db57c637364c322d3372e097840c72000dabdcf6156e" "checksum num-bigint 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)" = "e63899ad0da84ce718c14936262a41cee2c79c981fc0a0e7c7beb47d5a07e8c1" "checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" +"checksum num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "af3fdbbc3291a5464dc57b03860ec37ca6bf915ed6ee385e7c6c052c422b2124" "checksum num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" "checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" "checksum num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a23f0ed30a54abaa0c7e83b1d2d87ada7c3c23078d1d87815af3e3b6385fbba" @@ -2334,6 +2377,8 @@ dependencies = [ "checksum safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dca453248a96cb0749e36ccdfe2b0b4e54a61bfef89fb97ec621eb8e0a93dd9" "checksum scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "332ffa32bf586782a3efaeb58f127980944bbc8c4d6913a86107ac2a5ab24b28" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" +"checksum sdl2 0.32.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0ebf85f207d42e4da59fa31fff977be5ff0b224873506c4bd70cc1c94b331593" +"checksum sdl2-sys 0.32.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e82803e85c2e6178d28886cef25b2c53afc2eecaeff739f2247f23ed3352e6c1" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" "checksum serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)" = "92514fb95f900c9b5126e32d020f5c6d40564c27a5ea6d1d7d9f157a96623560" diff --git a/Cargo.toml b/Cargo.toml index 1e88e82f..b3c230c6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -61,6 +61,7 @@ portaudio-backend = ["librespot-playback/portaudio-backend"] pulseaudio-backend = ["librespot-playback/pulseaudio-backend"] jackaudio-backend = ["librespot-playback/jackaudio-backend"] rodio-backend = ["librespot-playback/rodio-backend"] +sdl-backend = ["librespot-playback/sdl-backend"] with-tremor = ["librespot-audio/with-tremor"] with-vorbis = ["librespot-audio/with-vorbis"] diff --git a/playback/Cargo.toml b/playback/Cargo.toml index 2efd6ca6..0dff2a70 100644 --- a/playback/Cargo.toml +++ b/playback/Cargo.toml @@ -22,6 +22,7 @@ jack = { version = "0.5.3", optional = true } libc = { version = "0.2", optional = true } rodio = { git = "https://github.com/tomaka/rodio", optional = true, default-features = false } cpal = { version = "*", optional = true } +sdl2 = { version = "0.32", optional = true } [features] alsa-backend = ["alsa"] @@ -29,3 +30,4 @@ portaudio-backend = ["portaudio-rs"] pulseaudio-backend = ["libpulse-sys", "libc"] jackaudio-backend = ["jack"] rodio-backend = ["rodio", "cpal"] +sdl-backend = ["sdl2"] diff --git a/playback/src/audio_backend/mod.rs b/playback/src/audio_backend/mod.rs index 85e05d55..bdf309a8 100644 --- a/playback/src/audio_backend/mod.rs +++ b/playback/src/audio_backend/mod.rs @@ -38,6 +38,10 @@ use self::jackaudio::JackSink; mod rodio; #[cfg(feature = "rodio-backend")] use self::rodio::RodioSink; +#[cfg(feature = "sdl-backend")] +mod sdl; +#[cfg(feature = "sdl-backend")] +use self::sdl::SdlSink; mod pipe; use self::pipe::StdoutSink; @@ -53,6 +57,8 @@ pub const BACKENDS: &'static [(&'static str, fn(Option) -> Box)] = ("jackaudio", mk_sink::), #[cfg(feature = "rodio-backend")] ("rodio", mk_sink::), + #[cfg(feature = "sdl-backend")] + ("sdl", mk_sink::), ("pipe", mk_sink::), ]; diff --git a/playback/src/audio_backend/sdl.rs b/playback/src/audio_backend/sdl.rs new file mode 100644 index 00000000..707359cc --- /dev/null +++ b/playback/src/audio_backend/sdl.rs @@ -0,0 +1,56 @@ +use super::{Open, Sink}; +use sdl2::audio::{AudioQueue, AudioSpecDesired}; +use std::{io, thread, time}; + +type Channel = i16; + +pub struct SdlSink { + queue: AudioQueue, +} + +impl Open for SdlSink { + fn open(device: Option) -> SdlSink { + debug!("Using SDL sink"); + + if device.is_some() { + panic!("SDL sink does not support specifyng a device name"); + } + + let ctx = sdl2::init().expect("Could not init SDL"); + let audio = ctx.audio().expect("Could not init SDL audio subsystem"); + + let desired_spec = AudioSpecDesired { + freq: Some(44_100), + channels: Some(2), + samples: None, // default + }; + let queue = audio + .open_queue(None, &desired_spec) + .expect("Could not open SDL audio device"); + + SdlSink { queue: queue } + } +} + +impl Sink for SdlSink { + fn start(&mut self) -> io::Result<()> { + self.queue.clear(); // + self.queue.resume(); + Ok(()) + } + + fn stop(&mut self) -> io::Result<()> { + self.queue.pause(); + self.queue.clear(); + Ok(()) + } + + fn write(&mut self, data: &[i16]) -> io::Result<()> { + while self.queue.size() > (2 * 2 * 44_100) { + // sleep and wait for sdl thread to drain the queue a bit + thread::sleep(time::Duration::from_millis(10)); + } + self.queue.queue(data); + Ok(()) + } +} diff --git a/playback/src/lib.rs b/playback/src/lib.rs index afce662c..557e17ff 100644 --- a/playback/src/lib.rs +++ b/playback/src/lib.rs @@ -16,6 +16,9 @@ extern crate libpulse_sys; #[cfg(feature = "jackaudio-backend")] extern crate jack; +#[cfg(feature = "sdl-backend")] +extern crate sdl2; + #[cfg(feature = "libc")] extern crate libc;