From 555274b5afeee5ea0e271fbe50ee535fa48d4ea9 Mon Sep 17 00:00:00 2001 From: johannesd3 Date: Tue, 13 Apr 2021 10:29:34 +0200 Subject: [PATCH] Move decoder to playback crate --- .github/workflows/test.yml | 1 - CHANGELOG.md | 4 + Cargo.lock | 11 ++- Cargo.toml | 4 +- audio/Cargo.toml | 11 --- audio/src/lib.rs | 77 ------------------- playback/Cargo.toml | 12 ++- playback/src/audio_backend/alsa.rs | 2 +- playback/src/audio_backend/gstreamer.rs | 2 +- playback/src/audio_backend/jackaudio.rs | 2 +- playback/src/audio_backend/mod.rs | 4 +- playback/src/audio_backend/pipe.rs | 2 +- playback/src/audio_backend/portaudio.rs | 3 +- playback/src/audio_backend/pulseaudio.rs | 2 +- playback/src/audio_backend/rodio.rs | 3 +- playback/src/audio_backend/sdl.rs | 3 +- playback/src/audio_backend/subprocess.rs | 2 +- playback/src/config.rs | 2 +- {audio => playback}/src/convert.rs | 0 .../src/decoder}/lewton_decoder.rs | 0 .../src/decoder}/libvorbis_decoder.rs | 0 playback/src/decoder/mod.rs | 76 ++++++++++++++++++ .../src/decoder}/passthrough_decoder.rs | 0 playback/src/lib.rs | 2 + playback/src/player.rs | 2 +- 25 files changed, 116 insertions(+), 111 deletions(-) rename {audio => playback}/src/convert.rs (100%) rename {audio/src => playback/src/decoder}/lewton_decoder.rs (100%) rename {audio/src => playback/src/decoder}/libvorbis_decoder.rs (100%) create mode 100644 playback/src/decoder/mod.rs rename {audio/src => playback/src/decoder}/passthrough_decoder.rs (100%) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5c04cbb1..825fc936 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -99,7 +99,6 @@ jobs: - run: cargo hack --workspace --remove-dev-deps - run: cargo build -p librespot-core --no-default-features - run: cargo build -p librespot-core - - run: cargo hack build --each-feature -p librespot-audio - run: cargo build -p librespot-connect - run: cargo build -p librespot-connect --no-default-features --features with-dns-sd - run: cargo hack build --each-feature diff --git a/CHANGELOG.md b/CHANGELOG.md index b9bf71ec..f1e6ae1d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Removed + +* [librespot-audio] Removed `VorbisDecoder`, `VorbisError`, `AudioPacket`, `PassthroughDecoder`, `PassthroughError`, `AudioError`, `AudioDecoder` and the `convert` module from `librespot_audio`. The underlying crates `vorbis`, `librespot-tremor`, `lewton` and `ogg` should be used directly. + ## [0.2.0] - 2021-05-04 ## [0.1.6] - 2021-02-22 diff --git a/Cargo.lock b/Cargo.lock index 5019bb04..ea4e9bb9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1159,17 +1159,11 @@ dependencies = [ "aes-ctr", "byteorder", "bytes", - "cfg-if 1.0.0", "futures-util", - "lewton", "librespot-core", - "librespot-tremor", "log", - "ogg", "tempfile", "tokio", - "vorbis", - "zerocopy", ] [[package]] @@ -1257,6 +1251,7 @@ version = "0.2.0" dependencies = [ "alsa", "byteorder", + "cfg-if 1.0.0", "cpal", "futures-executor", "futures-util", @@ -1264,18 +1259,22 @@ dependencies = [ "gstreamer", "gstreamer-app", "jack 0.7.0", + "lewton", "libpulse-binding", "libpulse-simple-binding", "librespot-audio", "librespot-core", "librespot-metadata", + "librespot-tremor", "log", + "ogg", "portaudio-rs", "rodio", "sdl2", "shell-words", "thiserror", "tokio", + "vorbis", "zerocopy", ] diff --git a/Cargo.toml b/Cargo.toml index 3247f68a..081cacae 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -69,8 +69,8 @@ rodiojack-backend = ["librespot-playback/rodiojack-backend"] sdl-backend = ["librespot-playback/sdl-backend"] gstreamer-backend = ["librespot-playback/gstreamer-backend"] -with-tremor = ["librespot-audio/with-tremor"] -with-vorbis = ["librespot-audio/with-vorbis"] +with-tremor = ["librespot-playback/with-tremor"] +with-vorbis = ["librespot-playback/with-vorbis"] with-dns-sd = ["librespot-connect/with-dns-sd"] diff --git a/audio/Cargo.toml b/audio/Cargo.toml index 0154c9db..f4440592 100644 --- a/audio/Cargo.toml +++ b/audio/Cargo.toml @@ -14,18 +14,7 @@ version = "0.2.0" aes-ctr = "0.6" byteorder = "1.4" bytes = "1.0" -cfg-if = "1" -lewton = "0.10" log = "0.4" futures-util = { version = "0.3", default_features = false } -ogg = "0.8" tempfile = "3.1" tokio = { version = "1", features = ["sync", "macros"] } -zerocopy = "0.3" - -librespot-tremor = { version = "0.2", optional = true } -vorbis = { version ="0.0", optional = true } - -[features] -with-tremor = ["librespot-tremor"] -with-vorbis = ["vorbis"] diff --git a/audio/src/lib.rs b/audio/src/lib.rs index b587f038..e43cf728 100644 --- a/audio/src/lib.rs +++ b/audio/src/lib.rs @@ -3,25 +3,9 @@ #[macro_use] extern crate log; -pub mod convert; mod decrypt; mod fetch; -use cfg_if::cfg_if; - -cfg_if! { - if #[cfg(any(feature = "with-tremor", feature = "with-vorbis"))] { - mod libvorbis_decoder; - pub use crate::libvorbis_decoder::{VorbisDecoder, VorbisError}; - } else { - mod lewton_decoder; - pub use lewton_decoder::{VorbisDecoder, VorbisError}; - } -} - -mod passthrough_decoder; -pub use passthrough_decoder::{PassthroughDecoder, PassthroughError}; - mod range_set; pub use decrypt::AudioDecrypt; @@ -30,64 +14,3 @@ pub use fetch::{ READ_AHEAD_BEFORE_PLAYBACK_ROUNDTRIPS, READ_AHEAD_BEFORE_PLAYBACK_SECONDS, READ_AHEAD_DURING_PLAYBACK_ROUNDTRIPS, READ_AHEAD_DURING_PLAYBACK_SECONDS, }; -use std::fmt; - -pub enum AudioPacket { - Samples(Vec), - OggData(Vec), -} - -impl AudioPacket { - pub fn samples(&self) -> &[f32] { - match self { - AudioPacket::Samples(s) => s, - AudioPacket::OggData(_) => panic!("can't return OggData on samples"), - } - } - - pub fn oggdata(&self) -> &[u8] { - match self { - AudioPacket::Samples(_) => panic!("can't return samples on OggData"), - AudioPacket::OggData(d) => d, - } - } - - pub fn is_empty(&self) -> bool { - match self { - AudioPacket::Samples(s) => s.is_empty(), - AudioPacket::OggData(d) => d.is_empty(), - } - } -} - -#[derive(Debug)] -pub enum AudioError { - PassthroughError(PassthroughError), - VorbisError(VorbisError), -} - -impl fmt::Display for AudioError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - AudioError::PassthroughError(err) => write!(f, "PassthroughError({})", err), - AudioError::VorbisError(err) => write!(f, "VorbisError({})", err), - } - } -} - -impl From for AudioError { - fn from(err: VorbisError) -> AudioError { - AudioError::VorbisError(err) - } -} - -impl From for AudioError { - fn from(err: PassthroughError) -> AudioError { - AudioError::PassthroughError(err) - } -} - -pub trait AudioDecoder { - fn seek(&mut self, ms: i64) -> Result<(), AudioError>; - fn next_packet(&mut self) -> Result, AudioError>; -} diff --git a/playback/Cargo.toml b/playback/Cargo.toml index 2b3ccb5a..0f90d80f 100644 --- a/playback/Cargo.toml +++ b/playback/Cargo.toml @@ -18,12 +18,14 @@ path = "../metadata" version = "0.2.0" [dependencies] +cfg-if = "1.0" futures-executor = "0.3" futures-util = { version = "0.3", default_features = false, features = ["alloc"] } log = "0.4" byteorder = "1.4" shell-words = "1.0.0" tokio = { version = "1", features = ["sync"] } +zerocopy = { version = "0.3" } alsa = { version = "0.5", optional = true } portaudio-rs = { version = "0.3", optional = true } @@ -34,13 +36,18 @@ sdl2 = { version = "0.34.3", optional = true } gstreamer = { version = "0.16", optional = true } gstreamer-app = { version = "0.16", optional = true } glib = { version = "0.10", optional = true } -zerocopy = { version = "0.3" } # Rodio dependencies rodio = { version = "0.13", optional = true, default-features = false } cpal = { version = "0.13", optional = true } thiserror = { version = "1", optional = true } +# Decoders +lewton = "0.10" # Currently not optional because of limitations of cargo features +librespot-tremor = { version = "0.2", optional = true } +ogg = "0.8" +vorbis = { version ="0.0", optional = true } + [features] alsa-backend = ["alsa"] portaudio-backend = ["portaudio-rs"] @@ -50,3 +57,6 @@ rodio-backend = ["rodio", "cpal", "thiserror"] rodiojack-backend = ["rodio", "cpal/jack", "thiserror"] sdl-backend = ["sdl2"] gstreamer-backend = ["gstreamer", "gstreamer-app", "glib"] + +with-tremor = ["librespot-tremor"] +with-vorbis = ["vorbis"] \ No newline at end of file diff --git a/playback/src/audio_backend/alsa.rs b/playback/src/audio_backend/alsa.rs index 54fed319..c7bc4e55 100644 --- a/playback/src/audio_backend/alsa.rs +++ b/playback/src/audio_backend/alsa.rs @@ -1,6 +1,6 @@ use super::{Open, Sink, SinkAsBytes}; -use crate::audio::AudioPacket; use crate::config::AudioFormat; +use crate::decoder::AudioPacket; use crate::player::{NUM_CHANNELS, SAMPLES_PER_SECOND, SAMPLE_RATE}; use alsa::device_name::HintIter; use alsa::pcm::{Access, Format, Frames, HwParams, PCM}; diff --git a/playback/src/audio_backend/gstreamer.rs b/playback/src/audio_backend/gstreamer.rs index 93b718dc..e31c66ae 100644 --- a/playback/src/audio_backend/gstreamer.rs +++ b/playback/src/audio_backend/gstreamer.rs @@ -1,6 +1,6 @@ use super::{Open, Sink, SinkAsBytes}; -use crate::audio::AudioPacket; use crate::config::AudioFormat; +use crate::decoder::AudioPacket; use crate::player::{NUM_CHANNELS, SAMPLE_RATE}; use gstreamer as gst; diff --git a/playback/src/audio_backend/jackaudio.rs b/playback/src/audio_backend/jackaudio.rs index aca2edd2..816147ff 100644 --- a/playback/src/audio_backend/jackaudio.rs +++ b/playback/src/audio_backend/jackaudio.rs @@ -1,6 +1,6 @@ use super::{Open, Sink}; -use crate::audio::AudioPacket; use crate::config::AudioFormat; +use crate::decoder::AudioPacket; use crate::player::NUM_CHANNELS; use jack::{ AsyncClient, AudioOut, Client, ClientOptions, Control, Port, ProcessHandler, ProcessScope, diff --git a/playback/src/audio_backend/mod.rs b/playback/src/audio_backend/mod.rs index 72659f19..84e35634 100644 --- a/playback/src/audio_backend/mod.rs +++ b/playback/src/audio_backend/mod.rs @@ -1,5 +1,5 @@ -use crate::audio::AudioPacket; use crate::config::AudioFormat; +use crate::decoder::AudioPacket; use std::io; pub trait Open { @@ -26,7 +26,7 @@ fn mk_sink(device: Option, format: AudioFormat macro_rules! sink_as_bytes { () => { fn write(&mut self, packet: &AudioPacket) -> io::Result<()> { - use crate::audio::convert::{self, i24}; + use crate::convert::{self, i24}; use zerocopy::AsBytes; match packet { AudioPacket::Samples(samples) => match self.format { diff --git a/playback/src/audio_backend/pipe.rs b/playback/src/audio_backend/pipe.rs index 4c6f27c1..df3e6c0f 100644 --- a/playback/src/audio_backend/pipe.rs +++ b/playback/src/audio_backend/pipe.rs @@ -1,6 +1,6 @@ use super::{Open, Sink, SinkAsBytes}; -use crate::audio::AudioPacket; use crate::config::AudioFormat; +use crate::decoder::AudioPacket; use std::fs::OpenOptions; use std::io::{self, Write}; diff --git a/playback/src/audio_backend/portaudio.rs b/playback/src/audio_backend/portaudio.rs index 234a9af6..4fe471a9 100644 --- a/playback/src/audio_backend/portaudio.rs +++ b/playback/src/audio_backend/portaudio.rs @@ -1,6 +1,7 @@ use super::{Open, Sink}; -use crate::audio::{convert, AudioPacket}; use crate::config::AudioFormat; +use crate::convert; +use crate::decoder::AudioPacket; use crate::player::{NUM_CHANNELS, SAMPLE_RATE}; use portaudio_rs::device::{get_default_output_index, DeviceIndex, DeviceInfo}; use portaudio_rs::stream::*; diff --git a/playback/src/audio_backend/pulseaudio.rs b/playback/src/audio_backend/pulseaudio.rs index b165c0b2..90a4a67a 100644 --- a/playback/src/audio_backend/pulseaudio.rs +++ b/playback/src/audio_backend/pulseaudio.rs @@ -1,6 +1,6 @@ use super::{Open, Sink, SinkAsBytes}; -use crate::audio::AudioPacket; use crate::config::AudioFormat; +use crate::decoder::AudioPacket; use crate::player::{NUM_CHANNELS, SAMPLE_RATE}; use libpulse_binding::{self as pulse, stream::Direction}; use libpulse_simple_binding::Simple; diff --git a/playback/src/audio_backend/rodio.rs b/playback/src/audio_backend/rodio.rs index ebbdd256..9399a309 100644 --- a/playback/src/audio_backend/rodio.rs +++ b/playback/src/audio_backend/rodio.rs @@ -5,8 +5,9 @@ use cpal::traits::{DeviceTrait, HostTrait}; use thiserror::Error; use super::Sink; -use crate::audio::{convert, AudioPacket}; use crate::config::AudioFormat; +use crate::convert; +use crate::decoder::AudioPacket; use crate::player::{NUM_CHANNELS, SAMPLE_RATE}; #[cfg(all( diff --git a/playback/src/audio_backend/sdl.rs b/playback/src/audio_backend/sdl.rs index 29566533..a3a608d9 100644 --- a/playback/src/audio_backend/sdl.rs +++ b/playback/src/audio_backend/sdl.rs @@ -1,6 +1,7 @@ use super::{Open, Sink}; -use crate::audio::{convert, AudioPacket}; use crate::config::AudioFormat; +use crate::convert; +use crate::decoder::AudioPacket; use crate::player::{NUM_CHANNELS, SAMPLE_RATE}; use sdl2::audio::{AudioQueue, AudioSpecDesired}; use std::{io, thread, time}; diff --git a/playback/src/audio_backend/subprocess.rs b/playback/src/audio_backend/subprocess.rs index b4af1b40..f493e7a7 100644 --- a/playback/src/audio_backend/subprocess.rs +++ b/playback/src/audio_backend/subprocess.rs @@ -1,6 +1,6 @@ use super::{Open, Sink, SinkAsBytes}; -use crate::audio::AudioPacket; use crate::config::AudioFormat; +use crate::decoder::AudioPacket; use shell_words::split; use std::io::{self, Write}; diff --git a/playback/src/config.rs b/playback/src/config.rs index f8f02893..3ae0f34f 100644 --- a/playback/src/config.rs +++ b/playback/src/config.rs @@ -1,4 +1,4 @@ -use crate::audio::convert::i24; +use crate::convert::i24; use std::convert::TryFrom; use std::mem; use std::str::FromStr; diff --git a/audio/src/convert.rs b/playback/src/convert.rs similarity index 100% rename from audio/src/convert.rs rename to playback/src/convert.rs diff --git a/audio/src/lewton_decoder.rs b/playback/src/decoder/lewton_decoder.rs similarity index 100% rename from audio/src/lewton_decoder.rs rename to playback/src/decoder/lewton_decoder.rs diff --git a/audio/src/libvorbis_decoder.rs b/playback/src/decoder/libvorbis_decoder.rs similarity index 100% rename from audio/src/libvorbis_decoder.rs rename to playback/src/decoder/libvorbis_decoder.rs diff --git a/playback/src/decoder/mod.rs b/playback/src/decoder/mod.rs new file mode 100644 index 00000000..6108f00f --- /dev/null +++ b/playback/src/decoder/mod.rs @@ -0,0 +1,76 @@ +use std::fmt; + +use cfg_if::cfg_if; + +cfg_if! { + if #[cfg(any(feature = "with-tremor", feature = "with-vorbis"))] { + mod libvorbis_decoder; + pub use libvorbis_decoder::{VorbisDecoder, VorbisError}; + } else { + mod lewton_decoder; + pub use lewton_decoder::{VorbisDecoder, VorbisError}; + } +} + +mod passthrough_decoder; +pub use passthrough_decoder::{PassthroughDecoder, PassthroughError}; + +pub enum AudioPacket { + Samples(Vec), + OggData(Vec), +} + +impl AudioPacket { + pub fn samples(&self) -> &[f32] { + match self { + AudioPacket::Samples(s) => s, + AudioPacket::OggData(_) => panic!("can't return OggData on samples"), + } + } + + pub fn oggdata(&self) -> &[u8] { + match self { + AudioPacket::Samples(_) => panic!("can't return samples on OggData"), + AudioPacket::OggData(d) => d, + } + } + + pub fn is_empty(&self) -> bool { + match self { + AudioPacket::Samples(s) => s.is_empty(), + AudioPacket::OggData(d) => d.is_empty(), + } + } +} + +#[derive(Debug)] +pub enum AudioError { + PassthroughError(PassthroughError), + VorbisError(VorbisError), +} + +impl fmt::Display for AudioError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + AudioError::PassthroughError(err) => write!(f, "PassthroughError({})", err), + AudioError::VorbisError(err) => write!(f, "VorbisError({})", err), + } + } +} + +impl From for AudioError { + fn from(err: VorbisError) -> AudioError { + AudioError::VorbisError(err) + } +} + +impl From for AudioError { + fn from(err: PassthroughError) -> AudioError { + AudioError::PassthroughError(err) + } +} + +pub trait AudioDecoder { + fn seek(&mut self, ms: i64) -> Result<(), AudioError>; + fn next_packet(&mut self) -> Result, AudioError>; +} diff --git a/audio/src/passthrough_decoder.rs b/playback/src/decoder/passthrough_decoder.rs similarity index 100% rename from audio/src/passthrough_decoder.rs rename to playback/src/decoder/passthrough_decoder.rs diff --git a/playback/src/lib.rs b/playback/src/lib.rs index 9613f2e5..58423380 100644 --- a/playback/src/lib.rs +++ b/playback/src/lib.rs @@ -7,5 +7,7 @@ use librespot_metadata as metadata; pub mod audio_backend; pub mod config; +mod convert; +mod decoder; pub mod mixer; pub mod player; diff --git a/playback/src/player.rs b/playback/src/player.rs index 0127f00a..bdfd80be 100644 --- a/playback/src/player.rs +++ b/playback/src/player.rs @@ -11,7 +11,6 @@ use futures_util::stream::futures_unordered::FuturesUnordered; use futures_util::{future, StreamExt, TryFutureExt}; use tokio::sync::{mpsc, oneshot}; -use crate::audio::{AudioDecoder, AudioError, AudioPacket, PassthroughDecoder, VorbisDecoder}; use crate::audio::{AudioDecrypt, AudioFile, StreamLoaderController}; use crate::audio::{ READ_AHEAD_BEFORE_PLAYBACK_ROUNDTRIPS, READ_AHEAD_BEFORE_PLAYBACK_SECONDS, @@ -22,6 +21,7 @@ use crate::config::{Bitrate, NormalisationMethod, NormalisationType, PlayerConfi use crate::core::session::Session; use crate::core::spotify_id::SpotifyId; use crate::core::util::SeqGenerator; +use crate::decoder::{AudioDecoder, AudioError, AudioPacket, PassthroughDecoder, VorbisDecoder}; use crate::metadata::{AudioItem, FileFormat}; use crate::mixer::AudioFilter;