diff --git a/src/video.rs b/src/video.rs index b77b1a4..0ca851d 100644 --- a/src/video.rs +++ b/src/video.rs @@ -67,6 +67,7 @@ pub(crate) struct Internal { pub(crate) sync_av_counter: u64, pub(crate) subtitle_text: Arc>>, + pub(crate) upload_text: Arc, } impl Internal { @@ -279,9 +280,13 @@ impl Video { let paused_ref = Arc::clone(&paused); let subtitle_text = Arc::new(Mutex::new(None)); + let upload_text = Arc::new(AtomicBool::new(false)); let subtitle_text_ref = Arc::clone(&subtitle_text); + let upload_text_ref = Arc::clone(&upload_text); let worker = std::thread::spawn(move || { + let mut clear_subtitles_at = None; + while alive_ref.load(Ordering::Acquire) { if let Err(gst::FlowError::Error) = (|| -> Result<(), gst::FlowError> { let sample = if paused_ref.load(Ordering::SeqCst) { @@ -307,12 +312,24 @@ impl Video { upload_frame_ref.swap(true, Ordering::SeqCst); + if let Some(at) = clear_subtitles_at.clone() { + if Instant::now() >= at { + *subtitle_text_ref + .lock() + .map_err(|_| gst::FlowError::Error)? = None; + upload_text_ref.store(true, Ordering::SeqCst); + clear_subtitles_at = None; + } + } + let text = text_sink .as_ref() .and_then(|sink| sink.try_pull_sample(gst::ClockTime::from_seconds(0))); if let Some(text) = text { let text = text.buffer().ok_or(gst::FlowError::Error)?; + let duration = text.duration(); let map = text.map_readable().map_err(|_| gst::FlowError::Error)?; + let text = html_escape::decode_html_entities( std::str::from_utf8(map.as_slice()) .map_err(|_| gst::FlowError::Error)?, @@ -321,6 +338,11 @@ impl Video { *subtitle_text_ref .lock() .map_err(|_| gst::FlowError::Error)? = Some(text); + upload_text_ref.store(true, Ordering::SeqCst); + + clear_subtitles_at = duration.map(|duration| { + Instant::now() + Duration::from_nanos(duration.nseconds()) + }); } Ok(()) @@ -356,6 +378,7 @@ impl Video { sync_av_counter: 0, subtitle_text, + upload_text, }))) } diff --git a/src/video_player.rs b/src/video_player.rs index 8229317..ac6c9a2 100644 --- a/src/video_player.rs +++ b/src/video_player.rs @@ -20,7 +20,7 @@ where height: iced::Length, on_end_of_stream: Option, on_new_frame: Option, - on_subtitle_text: Option Message + 'a>>, + on_subtitle_text: Option) -> Message + 'a>>, on_error: Option Message + 'a>>, _phantom: PhantomData<(Theme, Renderer)>, } @@ -87,7 +87,7 @@ where /// Message to send when the video receives a new frame. pub fn on_subtitle_text(self, on_subtitle_text: F) -> Self where - F: 'a + Fn(String) -> Message, + F: 'a + Fn(Option) -> Message, { VideoPlayer { on_subtitle_text: Some(Box::new(on_subtitle_text)), @@ -273,13 +273,10 @@ where } if let Some(on_subtitle_text) = &self.on_subtitle_text { - if let Some(text) = inner - .subtitle_text - .try_lock() - .ok() - .and_then(|mut text| text.take()) - { - shell.publish(on_subtitle_text(text)); + if inner.upload_text.swap(false, Ordering::SeqCst) { + if let Some(text) = inner.subtitle_text.try_lock().ok() { + shell.publish(on_subtitle_text(text.clone())); + } } } }