Browse Source

Some clean up

Konstantin Seiler 4 years ago
parent
commit
9eef690a22
3 changed files with 81 additions and 268 deletions
  1. 8 9
      connect/src/spirc.rs
  2. 5 48
      examples/play.rs
  3. 68 211
      playback/src/player.rs

+ 8 - 9
connect/src/spirc.rs

@@ -546,14 +546,10 @@ impl SpircTask {
                     PlayerEvent::EndOfTrack { .. } => self.handle_end_of_track(),
                     PlayerEvent::Loading { .. } => (),
                     PlayerEvent::Playing { position_ms, .. } => {
-                        let new_nominal_start_time =
-                            self.now_ms() - position_ms as i64;
+                        let new_nominal_start_time = self.now_ms() - position_ms as i64;
                         match self.play_status {
                             SpircPlayStatus::Playing { nominal_start_time } => {
-                                if (nominal_start_time - new_nominal_start_time)
-                                    .abs()
-                                    > 100
-                                {
+                                if (nominal_start_time - new_nominal_start_time).abs() > 100 {
                                     self.update_state_position(position_ms);
                                     self.notify(None);
                                     self.play_status = SpircPlayStatus::Playing {
@@ -611,14 +607,17 @@ impl SpircTask {
                             self.play_status = SpircPlayStatus::Stopped;
                         }
                     },
-                    PlayerEvent::TimeToPreloadNextTrack {..} => match self.play_status {
-                        SpircPlayStatus::Paused {..}|SpircPlayStatus::Playing {..}| SpircPlayStatus::LoadingPause{..}|SpircPlayStatus::LoadingPlay {..} => {
+                    PlayerEvent::TimeToPreloadNextTrack { .. } => match self.play_status {
+                        SpircPlayStatus::Paused { .. }
+                        | SpircPlayStatus::Playing { .. }
+                        | SpircPlayStatus::LoadingPause { .. }
+                        | SpircPlayStatus::LoadingPlay { .. } => {
                             if let Some(track_id) = self.preview_next_track() {
                                 self.player.preload(track_id);
                             }
                         }
                         SpircPlayStatus::Stopped => (),
-                    }
+                    },
                     _ => (),
                 }
             }

+ 5 - 48
examples/play.rs

@@ -7,53 +7,8 @@ use librespot::core::session::Session;
 use librespot::core::spotify_id::SpotifyId;
 use librespot::playback::config::PlayerConfig;
 
-use futures::stream::Stream;
-use futures::{Async, Future, Poll};
 use librespot::playback::audio_backend;
-use librespot::playback::player::{Player, PlayerEvent, PlayerEventChannel};
-
-pub struct SingleTrackPlayer {
-    play_request_id: u64,
-    event_channel: PlayerEventChannel,
-}
-
-impl SingleTrackPlayer {
-    pub fn new(ref mut player: Player, track_id: SpotifyId) -> SingleTrackPlayer {
-        let event_channel = player.get_player_event_channel();
-        let play_request_id = player.load(track_id, true, 0);
-        SingleTrackPlayer {
-            play_request_id,
-            event_channel,
-        }
-    }
-}
-
-impl Future for SingleTrackPlayer {
-    type Item = ();
-    type Error = ();
-
-    fn poll(&mut self) -> Poll<(), ()> {
-        loop {
-            match self.event_channel.poll().unwrap() {
-                Async::NotReady => return Ok(Async::NotReady),
-                Async::Ready(None) => return Ok(Async::Ready(())),
-                Async::Ready(Some(event)) => match event {
-                    PlayerEvent::EndOfTrack {
-                        play_request_id, ..
-                    }
-                    | PlayerEvent::Stopped {
-                        play_request_id, ..
-                    } => {
-                        if play_request_id == self.play_request_id {
-                            return Ok(Async::Ready(()));
-                        }
-                    }
-                    _ => (),
-                },
-            }
-        }
-    }
-}
+use librespot::playback::player::Player;
 
 fn main() {
     let mut core = Core::new().unwrap();
@@ -79,12 +34,14 @@ fn main() {
         .run(Session::connect(session_config, credentials, None, handle))
         .unwrap();
 
-    let (player, _) = Player::new(player_config, session.clone(), None, move || {
+    let (mut player, _) = Player::new(player_config, session.clone(), None, move || {
         (backend)(None)
     });
 
+    player.load(track, true, 0);
+
     println!("Playing...");
-    core.run(SingleTrackPlayer::new(player, track)).unwrap();
+    core.run(player.get_end_of_track_future()).unwrap();
 
     println!("Done");
 }

+ 68 - 211
playback/src/player.rs

@@ -247,10 +247,8 @@ impl Player {
         play_request_id
     }
 
-    pub fn preload(&mut self, track_id: SpotifyId) {
-        self.command(PlayerCommand::Preload {
-            track_id,
-        });
+    pub fn preload(&self, track_id: SpotifyId) {
+        self.command(PlayerCommand::Preload { track_id });
     }
 
     pub fn play(&self) {
@@ -275,6 +273,19 @@ impl Player {
         event_receiver
     }
 
+    pub fn get_end_of_track_future(&self) -> Box<dyn Future<Item = (), Error = ()>> {
+        let result = self
+            .get_player_event_channel()
+            .filter(|event| match event {
+                PlayerEvent::EndOfTrack { .. } | PlayerEvent::Stopped { .. } => true,
+                _ => false,
+            })
+            .into_future()
+            .map_err(|_| ())
+            .map(|_| ());
+        Box::new(result)
+    }
+
     pub fn emit_volume_set_event(&self, volume: u16) {
         self.command(PlayerCommand::EmitVolumeSetEvent(volume));
     }
@@ -299,7 +310,7 @@ struct PlayerLoadedTrackData {
     stream_loader_controller: StreamLoaderController,
     bytes_per_second: usize,
     duration_ms: u32,
-    stream_position: u64,
+    stream_position_pcm: u64,
 }
 
 enum PlayerPreload {
@@ -332,7 +343,7 @@ enum PlayerState {
         stream_loader_controller: StreamLoaderController,
         bytes_per_second: usize,
         duration_ms: u32,
-        stream_position: u64,
+        stream_position_pcm: u64,
         suggested_to_preload_next_track: bool,
     },
     Playing {
@@ -343,7 +354,7 @@ enum PlayerState {
         stream_loader_controller: StreamLoaderController,
         bytes_per_second: usize,
         duration_ms: u32,
-        stream_position: u64,
+        stream_position_pcm: u64,
         reported_nominal_start_time: Option<Instant>,
         suggested_to_preload_next_track: bool,
     },
@@ -430,7 +441,7 @@ impl PlayerState {
                 stream_loader_controller,
                 duration_ms,
                 bytes_per_second,
-                stream_position,
+                stream_position_pcm,
                 suggested_to_preload_next_track,
             } => {
                 *self = Playing {
@@ -441,7 +452,7 @@ impl PlayerState {
                     stream_loader_controller,
                     duration_ms,
                     bytes_per_second,
-                    stream_position,
+                    stream_position_pcm,
                     reported_nominal_start_time: None,
                     suggested_to_preload_next_track,
                 };
@@ -461,7 +472,7 @@ impl PlayerState {
                 stream_loader_controller,
                 duration_ms,
                 bytes_per_second,
-                stream_position,
+                stream_position_pcm,
                 reported_nominal_start_time: _,
                 suggested_to_preload_next_track,
             } => {
@@ -473,7 +484,7 @@ impl PlayerState {
                     stream_loader_controller,
                     duration_ms,
                     bytes_per_second,
-                    stream_position,
+                    stream_position_pcm,
                     suggested_to_preload_next_track,
                 };
             }
@@ -526,7 +537,7 @@ impl PlayerTrackLoader {
         }
     }
 
-    fn load_track(&self, spotify_id: SpotifyId, position: u64) -> Option<PlayerLoadedTrackData> {
+    fn load_track(&self, spotify_id: SpotifyId, position_ms: u32) -> Option<PlayerLoadedTrackData> {
         let audio = match AudioItem::get_audio_item(&self.session, spotify_id).wait() {
             Ok(audio) => audio,
             Err(_) => {
@@ -580,7 +591,7 @@ impl PlayerTrackLoader {
         };
 
         let bytes_per_second = self.stream_data_rate(*format);
-        let play_from_beginning = position == 0;
+        let play_from_beginning = position_ms == 0;
 
         let key = self.session.audio_key().request(spotify_id, file_id);
         let encrypted_file = AudioFile::open(
@@ -632,14 +643,14 @@ impl PlayerTrackLoader {
 
         let mut decoder = VorbisDecoder::new(audio_file).unwrap();
 
-        if position != 0 {
-            match decoder.seek(position as i64) {
+        if position_ms != 0 {
+            match decoder.seek(position_ms as i64) {
                 Ok(_) => (),
                 Err(err) => error!("Vorbis error: {:?}", err),
             }
             stream_loader_controller.set_stream_mode();
         }
-        let stream_position = position * 441 / 10;
+        let stream_position_pcm = PlayerInternal::position_ms_to_pcm(position_ms);
         info!("<{}> ({} ms) loaded", audio.name, audio.duration);
         Some(PlayerLoadedTrackData {
             decoder,
@@ -647,7 +658,7 @@ impl PlayerTrackLoader {
             stream_loader_controller,
             bytes_per_second,
             duration_ms,
-            stream_position,
+            stream_position_pcm,
         })
     }
 }
@@ -736,7 +747,7 @@ impl Future for PlayerInternal {
                     play_request_id,
                     ref mut decoder,
                     normalisation_factor,
-                    ref mut stream_position,
+                    ref mut stream_position_pcm,
                     ref mut reported_nominal_start_time,
                     duration_ms,
                     ..
@@ -746,17 +757,18 @@ impl Future for PlayerInternal {
                     let packet = decoder.next_packet().expect("Vorbis error");
 
                     if let Some(ref packet) = packet {
-                        *stream_position = *stream_position + (packet.data().len() / 2) as u64;
-                        let stream_position_seconds = *stream_position / 44100;
-                        if stream_position_seconds != last_printed_stream_position_for_debug {
+                        *stream_position_pcm =
+                            *stream_position_pcm + (packet.data().len() / 2) as u64;
+                        let stream_position_millis = Self::position_pcm_to_ms(*stream_position_pcm);
+
+                        if stream_position_millis / 1000 != last_printed_stream_position_for_debug {
                             trace!(
                                 "Stream position: {} ({} seconds)",
-                                *stream_position,
-                                stream_position_seconds
+                                *stream_position_pcm,
+                                stream_position_millis / 1000
                             );
-                            last_printed_stream_position_for_debug = stream_position_seconds;
+                            last_printed_stream_position_for_debug = stream_position_millis / 1000;
                         }
-                        let stream_position_millis = *stream_position * 10 / 441;
 
                         let notify_about_position = match *reported_nominal_start_time {
                             None => true,
@@ -800,7 +812,7 @@ impl Future for PlayerInternal {
                 track_id,
                 play_request_id,
                 duration_ms,
-                stream_position,
+                stream_position_pcm,
                 ref mut stream_loader_controller,
                 ref mut suggested_to_preload_next_track,
                 ..
@@ -809,13 +821,13 @@ impl Future for PlayerInternal {
                 track_id,
                 play_request_id,
                 duration_ms,
-                stream_position,
+                stream_position_pcm,
                 ref mut stream_loader_controller,
                 ref mut suggested_to_preload_next_track,
                 ..
             } = self.state
             {
-                let stream_position_millis = stream_position * 10 / 441;
+                let stream_position_millis = Self::position_pcm_to_ms(stream_position_pcm);
                 if (!*suggested_to_preload_next_track)
                     && ((duration_ms as i64 - stream_position_millis as i64)
                         < PRELOAD_NEXT_TRACK_BEFORE_END_DURATION_MS as i64)
@@ -841,6 +853,14 @@ impl Future for PlayerInternal {
 }
 
 impl PlayerInternal {
+    fn position_pcm_to_ms(position_pcm: u64) -> u32 {
+        (position_pcm * 10 / 441) as u32
+    }
+
+    fn position_ms_to_pcm(position_ms: u32) -> u64 {
+        position_ms as u64 * 441 / 10
+    }
+
     fn start_sink(&mut self) {
         match self.sink.start() {
             Ok(()) => self.sink_running = true,
@@ -939,7 +959,7 @@ impl PlayerInternal {
         loaded_track: PlayerLoadedTrackData,
         start_playback: bool,
     ) {
-        let position_ms = (loaded_track.stream_position * 10 / 441) as u32;
+        let position_ms = Self::position_pcm_to_ms(loaded_track.stream_position_pcm);
 
         match self.state {
             PlayerState::Playing {
@@ -984,7 +1004,7 @@ impl PlayerInternal {
                 stream_loader_controller: loaded_track.stream_loader_controller,
                 duration_ms: loaded_track.duration_ms,
                 bytes_per_second: loaded_track.bytes_per_second,
-                stream_position: loaded_track.stream_position,
+                stream_position_pcm: loaded_track.stream_position_pcm,
                 reported_nominal_start_time: Some(
                     Instant::now() - Duration::from_millis(position_ms as u64),
                 ),
@@ -999,7 +1019,7 @@ impl PlayerInternal {
                 stream_loader_controller: loaded_track.stream_loader_controller,
                 duration_ms: loaded_track.duration_ms,
                 bytes_per_second: loaded_track.bytes_per_second,
-                stream_position: loaded_track.stream_position,
+                stream_position_pcm: loaded_track.stream_position_pcm,
                 suggested_to_preload_next_track: false,
             };
 
@@ -1102,8 +1122,7 @@ impl PlayerInternal {
 
                     self.preload = PlayerPreload::None;
 
-                    let loader = loader
-                        .or_else(|| Some(self.load_track_threaded(track_id, position_ms as u64)));
+                    let loader = loader.or_else(|| Some(self.load_track(track_id, position_ms)));
                     let loader = loader.unwrap();
 
                     self.state = PlayerState::Loading {
@@ -1130,28 +1149,28 @@ impl PlayerInternal {
                     }
                 }
                 if let PlayerPreload::None = self.preload {
-                    let loader = self.load_track_threaded(track_id, 0);
+                    let loader = self.load_track(track_id, 0);
                     self.preload = PlayerPreload::Loading { track_id, loader }
                 }
             }
 
-            PlayerCommand::Seek(position) => {
+            PlayerCommand::Seek(position_ms) => {
                 if let Some(stream_loader_controller) = self.state.stream_loader_controller() {
                     stream_loader_controller.set_random_access_mode();
                 }
                 if let Some(decoder) = self.state.decoder() {
-                    match decoder.seek(position as i64) {
+                    match decoder.seek(position_ms as i64) {
                         Ok(_) => {
                             if let PlayerState::Playing {
-                                ref mut stream_position,
+                                ref mut stream_position_pcm,
                                 ..
                             }
                             | PlayerState::Paused {
-                                ref mut stream_position,
+                                ref mut stream_position_pcm,
                                 ..
                             } = self.state
                             {
-                                *stream_position = position as u64 * 441 / 10;
+                                *stream_position_pcm = Self::position_ms_to_pcm(position_ms);
                             }
                         }
                         Err(err) => error!("Vorbis error: {:?}", err),
@@ -1176,11 +1195,11 @@ impl PlayerInternal {
                 } = self.state
                 {
                     *reported_nominal_start_time =
-                        Some(Instant::now() - Duration::from_millis(position as u64));
+                        Some(Instant::now() - Duration::from_millis(position_ms as u64));
                     self.send_event(PlayerEvent::Playing {
                         track_id,
                         play_request_id,
-                        position_ms: position,
+                        position_ms: position_ms,
                         duration_ms,
                     });
                 }
@@ -1194,7 +1213,7 @@ impl PlayerInternal {
                     self.send_event(PlayerEvent::Paused {
                         track_id,
                         play_request_id,
-                        position_ms: position,
+                        position_ms: position_ms,
                         duration_ms,
                     });
                 }
@@ -1204,13 +1223,13 @@ impl PlayerInternal {
                 if let PlayerState::Paused {
                     track_id,
                     play_request_id,
-                    stream_position,
+                    stream_position_pcm,
                     ..
                 } = self.state
                 {
                     self.state.paused_to_playing();
 
-                    let position_ms = (stream_position * 10 / 441) as u32;
+                    let position_ms = Self::position_pcm_to_ms(stream_position_pcm);
                     self.send_event(PlayerEvent::Started {
                         track_id,
                         play_request_id,
@@ -1226,7 +1245,7 @@ impl PlayerInternal {
                 if let PlayerState::Playing {
                     track_id,
                     play_request_id,
-                    stream_position,
+                    stream_position_pcm,
                     duration_ms,
                     ..
                 } = self.state
@@ -1234,7 +1253,7 @@ impl PlayerInternal {
                     self.state.playing_to_paused();
 
                     self.stop_sink_if_running();
-                    let position_ms = (stream_position * 10 / 441) as u32;
+                    let position_ms = Self::position_pcm_to_ms(stream_position_pcm);
                     self.send_event(PlayerEvent::Paused {
                         track_id,
                         play_request_id,
@@ -1268,48 +1287,10 @@ impl PlayerInternal {
         }
     }
 
-    //    fn find_available_alternative<'a>(&self, audio: &'a AudioItem) -> Option<Cow<'a, AudioItem>> {
-    //        if audio.available {
-    //            Some(Cow::Borrowed(audio))
-    //        } else {
-    //            if let Some(alternatives) = &audio.alternatives {
-    //                let alternatives = alternatives
-    //                    .iter()
-    //                    .map(|alt_id| AudioItem::get_audio_item(&self.session, *alt_id));
-    //                let alternatives = future::join_all(alternatives).wait().unwrap();
-    //                alternatives
-    //                    .into_iter()
-    //                    .find(|alt| alt.available)
-    //                    .map(Cow::Owned)
-    //            } else {
-    //                None
-    //            }
-    //        }
-    //    }
-
-    //    fn stream_data_rate(&self, format: FileFormat) -> usize {
-    //        match format {
-    //            FileFormat::OGG_VORBIS_96 => 12 * 1024,
-    //            FileFormat::OGG_VORBIS_160 => 20 * 1024,
-    //            FileFormat::OGG_VORBIS_320 => 40 * 1024,
-    //            FileFormat::MP3_256 => 32 * 1024,
-    //            FileFormat::MP3_320 => 40 * 1024,
-    //            FileFormat::MP3_160 => 20 * 1024,
-    //            FileFormat::MP3_96 => 12 * 1024,
-    //            FileFormat::MP3_160_ENC => 20 * 1024,
-    //            FileFormat::MP4_128_DUAL => 16 * 1024,
-    //            FileFormat::OTHER3 => 40 * 1024, // better some high guess than nothing
-    //            FileFormat::AAC_160 => 20 * 1024,
-    //            FileFormat::AAC_320 => 40 * 1024,
-    //            FileFormat::MP4_128 => 16 * 1024,
-    //            FileFormat::OTHER5 => 40 * 1024, // better some high guess than nothing
-    //        }
-    //    }
-
-    fn load_track_threaded(
+    fn load_track(
         &self,
         spotify_id: SpotifyId,
-        position: u64,
+        position_ms: u32,
     ) -> Box<dyn Future<Item = PlayerLoadedTrackData, Error = ()>> {
         // This method creates a future that returns the loaded stream and associated info.
         // Ideally all work should be done using asynchronous code. However, seek() on the
@@ -1326,7 +1307,7 @@ impl PlayerInternal {
 
         std::thread::spawn(move || {
             loader
-                .load_track(spotify_id, position)
+                .load_track(spotify_id, position_ms)
                 .and_then(move |data| {
                     let _ = result_tx.send(data);
                     Some(())
@@ -1336,130 +1317,6 @@ impl PlayerInternal {
         Box::new(result_rx.map_err(|_| ()))
     }
 
-    //    fn load_track(
-    //        &self,
-    //        spotify_id: SpotifyId,
-    //        position: u64,
-    //    ) -> Option<(Decoder, f32, StreamLoaderController, usize, u64)> {
-    //        let audio = match AudioItem::get_audio_item(&self.session, spotify_id).wait() {
-    //            Ok(audio) => audio,
-    //            Err(_) => {
-    //                error!("Unable to load audio item.");
-    //                return None;
-    //            }
-    //        };
-    //
-    //        info!("Loading <{}> with Spotify URI <{}>", audio.name, audio.uri);
-    //
-    //        let audio = match self.find_available_alternative(&audio) {
-    //            Some(audio) => audio,
-    //            None => {
-    //                warn!("<{}> is not available", audio.uri);
-    //                return None;
-    //            }
-    //        };
-    //        // (Most) podcasts seem to support only 96 bit Vorbis, so fall back to it
-    //        let formats = match self.config.bitrate {
-    //            Bitrate::Bitrate96 => [
-    //                FileFormat::OGG_VORBIS_96,
-    //                FileFormat::OGG_VORBIS_160,
-    //                FileFormat::OGG_VORBIS_320,
-    //            ],
-    //            Bitrate::Bitrate160 => [
-    //                FileFormat::OGG_VORBIS_160,
-    //                FileFormat::OGG_VORBIS_96,
-    //                FileFormat::OGG_VORBIS_320,
-    //            ],
-    //            Bitrate::Bitrate320 => [
-    //                FileFormat::OGG_VORBIS_320,
-    //                FileFormat::OGG_VORBIS_160,
-    //                FileFormat::OGG_VORBIS_96,
-    //            ],
-    //        };
-    //        let format = formats
-    //            .iter()
-    //            .find(|format| audio.files.contains_key(format))
-    //            .unwrap();
-    //
-    //        let file_id = match audio.files.get(&format) {
-    //            Some(&file_id) => file_id,
-    //            None => {
-    //                warn!("<{}> in not available in format {:?}", audio.name, format);
-    //                return None;
-    //            }
-    //        };
-    //
-    //        let bytes_per_second = self.stream_data_rate(*format);
-    //        let play_from_beginning = position == 0;
-    //
-    //        let key = self.session.audio_key().request(spotify_id, file_id);
-    //        let encrypted_file = AudioFile::open(
-    //            &self.session,
-    //            file_id,
-    //            bytes_per_second,
-    //            play_from_beginning,
-    //        );
-    //
-    //        let encrypted_file = match encrypted_file.wait() {
-    //            Ok(encrypted_file) => encrypted_file,
-    //            Err(_) => {
-    //                error!("Unable to load encrypted file.");
-    //                return None;
-    //            }
-    //        };
-    //
-    //        let mut stream_loader_controller = encrypted_file.get_stream_loader_controller();
-    //
-    //        if play_from_beginning {
-    //            // No need to seek -> we stream from the beginning
-    //            stream_loader_controller.set_stream_mode();
-    //        } else {
-    //            // we need to seek -> we set stream mode after the initial seek.
-    //            stream_loader_controller.set_random_access_mode();
-    //        }
-    //
-    //        let key = match key.wait() {
-    //            Ok(key) => key,
-    //            Err(_) => {
-    //                error!("Unable to load decryption key");
-    //                return None;
-    //            }
-    //        };
-    //
-    //        let mut decrypted_file = AudioDecrypt::new(key, encrypted_file);
-    //
-    //        let normalisation_factor = match NormalisationData::parse_from_file(&mut decrypted_file) {
-    //            Ok(normalisation_data) => {
-    //                NormalisationData::get_factor(&self.config, normalisation_data)
-    //            }
-    //            Err(_) => {
-    //                warn!("Unable to extract normalisation data, using default value.");
-    //                1.0 as f32
-    //            }
-    //        };
-    //
-    //        let audio_file = Subfile::new(decrypted_file, 0xa7);
-    //
-    //        let mut decoder = VorbisDecoder::new(audio_file).unwrap();
-    //
-    //        if position != 0 {
-    //            match decoder.seek(position as i64) {
-    //                Ok(_) => (),
-    //                Err(err) => error!("Vorbis error: {:?}", err),
-    //            }
-    //            stream_loader_controller.set_stream_mode();
-    //        }
-    //        let stream_position = position * 441 / 10;
-    //        info!("<{}> loaded", audio.name);
-    //        Some((
-    //            decoder,
-    //            normalisation_factor,
-    //            stream_loader_controller,
-    //            bytes_per_second,
-    //            stream_position,
-    //        ))
-    //    }
-
     fn preload_data_before_playback(&mut self) {
         if let PlayerState::Playing {
             bytes_per_second,