Skip to content

Commit

Permalink
adds draft of skip function and buttons
Browse files Browse the repository at this point in the history
  • Loading branch information
dvdsk committed Jan 16, 2021
1 parent d5185ab commit e376b8e
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 34 deletions.
37 changes: 29 additions & 8 deletions src/database/episodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ use eyre::eyre;
#[derive(Serialize, Deserialize, Debug)]
pub struct Episode {
pub stream_url: String,
/// the duration of the episode in seconds
pub duration: f32,
// description:
// author:
// pub_date:
Expand All @@ -21,24 +23,43 @@ fn url_from_extensions(item: &rss::Item) -> Option<String> {
let content = media.get("content")?;
let extention = content.first()?;
if extention.name() != "media:content" { return None }

extention.attrs().get("url").map(|u| u.clone())
}

fn length_from_extensions(item: &rss::Item) -> Option<f32> {
let media = item.extensions().get("media")?;
let content = media.get("content")?;
let extention = content.first()?;
dbg!(extention.attrs());
if extention.name() != "media:content" { return None }
// TODO FIXME find out what the key could be here
extention.attrs().get("url").map(|u| u.parse().ok()).flatten()
}

impl TryFrom<&rss::Item> for Episode {
type Error = eyre::Report;

fn try_from(item: &rss::Item) -> Result<Self, Self::Error> {
dbg!(&item);
let stream_url = if let Some(encl) = item.enclosure() {
encl.url().to_owned()
} else {
url_from_extensions(item)
.ok_or(eyre!("no link for feed item: {:?}", item))?
};
//try to get the url and duration from the description of the media object
let stream_url = item.enclosure().map(|encl| encl.url().to_owned());
let duration = item.enclosure().map(|encl| encl.length().parse().ok()).flatten();

//try to get the url and duration possible extensions
let stream_url = stream_url.or(url_from_extensions(item));
let duration = duration.or(length_from_extensions(item));

//try to get duration from any included itunes extensions
let duration = duration.or(item.itunes_ext()
.map(|ext| ext.duration()
.map(|d| d.parse().ok()).flatten()
).flatten());

let stream_url = stream_url.ok_or(eyre!("no link for feed item: {:?}", item))?;
let duration = duration.ok_or(eyre!("no duration known for item: {:?}", item))?;

Ok(Self {
stream_url,
duration,
})
}
}
Expand Down
14 changes: 4 additions & 10 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,16 +75,11 @@ impl Application for App {
Progress::ToShortError => log::warn!("stream was to short to play audio"),
Progress::StreamError(e) => log::error!("errored stream {}",e),
Progress::Started(rx) => self.player.rx = Some(rx),
Progress::Finished => self.player.current = play::Track::None,
Progress::Finished => (),
Progress::Advanced(p) => {
self.player.current.set_streampos(p);
if self.player.sink.empty() && p > 10f32 {
let rx = self.player.rx.take().unwrap();
let rx = Arc::try_unwrap(rx).unwrap();
let rx = rx.into_inner().unwrap();
let rrx = play::ReadableReciever::new(rx);
let source = rodio::Decoder::new_mp3(rrx).unwrap();
self.player.sink.append_seekable(source);
if self.player.stream_ready(p) {
self.player.start_play();
}
}
}
Expand All @@ -102,7 +97,7 @@ impl Application for App {
|x| Message::Podcasts(page::podcasts::Message::AddedPodcast(x.0,x.1)))
}
Message::Play(key) => {
self.player.play_stream(key);
self.player.add_stream(key);
Command::none()
}
Message::Skip(f) => {
Expand All @@ -123,7 +118,6 @@ impl Application for App {
}
fn subscription(&self) -> Subscription<Self::Message> {
if let play::Track::Stream(_,_,url) = &self.player.current {
log::info!("playing");
play::subscribe::play(url.to_owned()).map(Message::StreamProgress)
} else {
Subscription::none()
Expand Down
64 changes: 50 additions & 14 deletions src/play/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// use futures::Stream;
use std::time::Instant;
use std::sync::mpsc;
use bytes::Bytes;
use rodio::Decoder;
Expand Down Expand Up @@ -72,8 +73,7 @@ impl Track {
pub struct TrackInfo {
pub title: String,
pub paused: bool,
pub pos: f32,
pub length: f32,
pub duration: f32,
}

#[derive(Default)]
Expand All @@ -92,50 +92,86 @@ pub struct Player {
output_stream: rodio::OutputStream,
db: database::Episodes,
pub rx: Option<Arc<Mutex<mpsc::Receiver<bytes::Bytes>>>>,

last_started: Option<Instant>,
offset: f32,
}

impl Player {
pub fn from_db(db: &database::Episodes) -> Self {
let (stream, stream_handle) = rodio::OutputStream::try_default().unwrap();
let sink = rodio::Sink::try_new(&stream_handle).unwrap();
Self {
controls: Controls::default(),
controls: Controls { skip_dur: 5f32, .. Controls::default()},
current: Track::None,
sink,
output_stream: stream,
db: db.clone(),
rx: None,
last_started: None,
offset: 0f32,
}
}

pub fn play_stream(&mut self, key: database::episodes::Key) {
pub fn start_play(&mut self) {
let rx = self.rx.take().unwrap();
let rx = Arc::try_unwrap(rx).unwrap();
let rx = rx.into_inner().unwrap();
let rrx = ReadableReciever::new(rx);
let source = rodio::Decoder::new_mp3(rrx).unwrap();
self.sink.append_seekable(source);
self.last_started = Some(std::time::Instant::now());
self.offset = 0f32;
}

fn pos(&self) -> f32 {
let elapsed = self.last_started.map(|t| t.elapsed().as_secs_f32() ).unwrap_or(0f32);
self.offset+elapsed
}

pub fn add_stream(&mut self, key: database::episodes::Key) {
let meta = self.db.get(key).unwrap();
let url = meta.stream_url;
self.current = Track::Stream(
TrackInfo {
title: String::default(),
paused: false,
pos: 0.0,
length: 0.0,
}, 0f32, url);
duration: meta.duration,
},
0f32,
meta.stream_url);
}

pub fn stream_ready(&self, p: f32) -> bool {
self.sink.empty() && p > 10f32
}

pub fn skip(&mut self, dur: f32) {
self.sink.set_pos(dur);
dbg!(dur, self.pos());
let pos = self.pos();
let target = dbg!(f32::max(self.pos()+dur, 0f32));
let target = match &self.current {
Track::None => return,
Track::Stream(_, dl_pos, _) => dbg!(f32::min(target, dbg!(*dl_pos))),
Track::File(info, _) => f32::min(target, info.duration),
};
self.offset += (target-pos);
self.sink.set_pos(target);
}

pub fn view(&mut self) -> Column<Message> {
let mut column = Column::new();
match &self.current {
Track::None => column,
Track::Stream(info, pos, url) => {
let stream_progress_bar = iced::ProgressBar::new(0.0..=100.0, *pos);
Track::Stream(info, download, _) => {
let download_progress_bar = iced::ProgressBar::new(0.0..=100.0, *download);
let playback_bar = iced::ProgressBar::new(0.0..=info.duration, self.pos());
let controls = Self::view_controls(&mut self.controls, info);
column.push(stream_progress_bar).push(controls)
column.push(download_progress_bar).push(playback_bar).push(controls)
}
Track::File(info, path) => {
Track::File(info, _) => {
let playback_bar = iced::ProgressBar::new(0.0..=info.duration, self.pos());
let controls = Self::view_controls(&mut self.controls, info);
column.push(controls)
column.push(playback_bar).push(controls)
}
}
}
Expand Down
3 changes: 1 addition & 2 deletions src/play/subscribe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,7 @@ async fn stream_state_machine(current: State) -> Option<(Progress, State)>{
.map(|t| 100.0 * state.downloaded as f32/ t as f32)
.unwrap_or(0.0);
let progress = Progress::Advanced(percentage);
dbg!(&state.downloaded);
Some(if state.downloaded > 8_192 {
Some(if state.downloaded > 4096 {
(progress, State::Streaming(state))
} else {
(progress, State::Buffering(state))
Expand Down

0 comments on commit e376b8e

Please sign in to comment.