فهرست منبع

Refactored to have apply_volume in a specifix mixer

Daniel Romero 8 سال پیش
والد
کامیت
347bf05dbe
5فایلهای تغییر یافته به همراه75 افزوده شده و 24 حذف شده
  1. 1 0
      src/lib.rs
  2. 4 1
      src/main.rs
  3. 14 0
      src/mixer/mod.rs
  4. 46 0
      src/mixer/softmixer.rs
  5. 10 23
      src/player.rs

+ 1 - 0
src/lib.rs

@@ -60,6 +60,7 @@ pub mod player;
 pub mod stream;
 pub mod util;
 pub mod version;
+pub mod mixer;
 
 #[cfg(feature = "with-syntex")] include!(concat!(env!("OUT_DIR"), "/lib.rs"));
 #[cfg(not(feature = "with-syntex"))] include!("lib.in.rs");

+ 4 - 1
src/main.rs

@@ -18,6 +18,7 @@ use librespot::audio_backend::{self, BACKENDS};
 use librespot::cache::{Cache, DefaultCache, NoCache};
 use librespot::player::Player;
 use librespot::session::{Bitrate, Config, Session};
+use librespot::mixer::softmixer::SoftMixer;
 use librespot::version;
 
 fn usage(program: &str, opts: &getopts::Options) -> String {
@@ -120,8 +121,10 @@ fn setup(args: &[String]) -> (Session, Player) {
     matches.opt_str("password"));
     session.login(credentials).unwrap();
 
+    let mixer = SoftMixer::new();
+
     let device_name = matches.opt_str("device");
-    let player = Player::new(session.clone(), move || {
+    let player = Player::new(session.clone(), Box::new(mixer), move || {
         (backend)(device_name.as_ref().map(AsRef::as_ref))
     });
 

+ 14 - 0
src/mixer/mod.rs

@@ -0,0 +1,14 @@
+use std::borrow::Cow;
+
+pub mod softmixer;
+
+pub trait Mixer {
+    fn init(&mut self);
+    fn inuse(&mut self);
+    fn release(&mut self);
+    fn set(&mut self, volume: u16);
+    fn volume(&self) -> u16;
+    fn apply_volume<'a>(&mut self, data: &'a [i16]) -> Cow<'a, [i16]> {
+        Cow::Borrowed(data)
+    }
+}

+ 46 - 0
src/mixer/softmixer.rs

@@ -0,0 +1,46 @@
+use super::Mixer;
+use std::borrow::Cow;
+
+pub struct SoftMixer {
+    volume: u16,
+}
+
+impl SoftMixer {
+    pub fn new() -> SoftMixer {
+        SoftMixer {
+            volume: 0xFFFF
+        }
+    }
+}
+
+impl Mixer for SoftMixer {
+    fn init(&mut self) {
+    }
+    
+    fn inuse(&mut self) {
+    }
+
+    fn release(&mut self) {
+    }
+
+    fn set(&mut self, volume: u16) {
+        self.volume = volume;
+    }
+
+    fn volume(&self) -> u16 {
+        self.volume
+    }
+    fn apply_volume<'a>(&mut self, data: &'a [i16]) -> Cow<'a, [i16]> {
+        if self.volume == 0xFFFF {
+            Cow::Borrowed(data)
+        } else {
+            Cow::Owned(data.iter()
+                        .map(|&x| {
+                            (x as i32
+                                * self.volume as i32
+                                / 0xFFFF) as i16
+                        })
+                        .collect())
+        }
+    }
+}

+ 10 - 23
src/player.rs

@@ -7,6 +7,7 @@ use vorbis;
 
 use audio_decrypt::AudioDecrypt;
 use audio_backend::Sink;
+use mixer::Mixer;
 use metadata::{FileFormat, Track, TrackRef};
 use session::{Bitrate, Session};
 use util::{self, ReadSeek, SpotifyId, Subfile};
@@ -74,8 +75,9 @@ enum PlayerCommand {
 }
 
 impl Player {
-    pub fn new<F>(session: Session, sink_builder: F) -> Player
-        where F: FnOnce() -> Box<Sink> + Send + 'static {
+    pub fn new<F, M>(session: Session, mixer: Box<M>, sink_builder: F) -> Player
+        where F: FnOnce() -> Box<Sink> + Send + 'static,
+              M: Mixer + Send + 'static {
         let (cmd_tx, cmd_rx) = mpsc::channel();
 
         let state = Arc::new(Mutex::new(PlayerState {
@@ -83,7 +85,7 @@ impl Player {
             position_ms: 0,
             position_measured_at: 0,
             update_time: util::now_ms(),
-            volume: 0xFFFF,
+            volume: mixer.volume(),
             track: None,
             end_of_track: false,
         }));
@@ -97,7 +99,7 @@ impl Player {
             observers: observers.clone(),
         };
 
-        thread::spawn(move || internal.run(sink_builder()));
+        thread::spawn(move || internal.run(sink_builder(), mixer));
 
         Player {
             commands: cmd_tx,
@@ -147,21 +149,6 @@ impl Player {
     }
 }
 
-fn apply_volume(volume: u16, data: &[i16]) -> Cow<[i16]> {
-    // Fast path when volume is 100%
-    if volume == 0xFFFF {
-        Cow::Borrowed(data)
-    } else {
-        Cow::Owned(data.iter()
-                       .map(|&x| {
-                           (x as i32
-                            * volume as i32
-                            / 0xFFFF) as i16
-                       })
-                       .collect())
-    }
-}
-
 fn find_available_alternative<'a>(session: &Session, track: &'a Track) -> Option<Cow<'a, Track>> {
     if track.available {
         Some(Cow::Borrowed(track))
@@ -229,7 +216,7 @@ fn run_onstop(session: &Session) {
 }
 
 impl PlayerInternal {
-    fn run(self, mut sink: Box<Sink>) {
+    fn run(self, mut sink: Box<Sink>, mut mixer: Box<Mixer>) {
         let mut decoder = None;
 
         loop {
@@ -344,8 +331,9 @@ impl PlayerInternal {
                     run_onstop(&self.session);
                 }
                 Some(PlayerCommand::Volume(vol)) => {
+                    mixer.set(vol);
                     self.update(|state| {
-                        state.volume = vol;
+                        state.volume = mixer.volume();
                         true
                     });
                 }
@@ -371,8 +359,7 @@ impl PlayerInternal {
 
                 match packet {
                     Some(Ok(packet)) => {
-                        let buffer = apply_volume(self.state.lock().unwrap().volume,
-                                                  &packet.data);
+                        let buffer = mixer.apply_volume(&packet.data);
                         sink.write(&buffer).unwrap();
 
                         self.update(|state| {