summary refs log tree commit diff
path: root/src/app.rs
diff options
context:
space:
mode:
authorMalte Voos <git@mal.tc>2025-11-14 15:30:49 +0100
committerMalte Voos <git@mal.tc>2025-11-14 15:30:49 +0100
commita8457a25ccb9b1ef47f5ce9d7ac1a84c47600c9e (patch)
tree542b42d3316138043272faba42e0d1005f8403b6 /src/app.rs
parenta42a73378b7c527a5e4600544b2d7a86d68c5aac (diff)
downloadlleap-a8457a25ccb9b1ef47f5ce9d7ac1a84c47600c9e.tar.gz
lleap-a8457a25ccb9b1ef47f5ce9d7ac1a84c47600c9e.zip
implement file/url open dialog
Diffstat (limited to 'src/app.rs')
-rw-r--r--src/app.rs84
1 files changed, 56 insertions, 28 deletions
diff --git a/src/app.rs b/src/app.rs
index 18f03e8..7aa5abd 100644
--- a/src/app.rs
+++ b/src/app.rs
@@ -2,26 +2,27 @@ use adw::prelude::*;
 use relm4::{WorkerController, prelude::*};
 
 use crate::{
+    open_dialog::{OpenDialog, OpenDialogMsg, OpenDialogOutput},
     player::{Player, PlayerMsg, PlayerOutput},
     preferences::{Preferences, PreferencesMsg},
-    subtitle_extractor::{
-        StreamIndex, SubtitleExtractor, SubtitleExtractorMsg, SubtitleExtractorOutput, TRACKS,
-    },
+    subtitle_extraction::{SubtitleExtractor, SubtitleExtractorMsg, SubtitleExtractorOutput},
     subtitle_selection_dialog::{
         SubtitleSelectionDialog, SubtitleSelectionDialogMsg, SubtitleSelectionDialogOutput,
     },
     subtitle_view::{SubtitleView, SubtitleViewMsg, SubtitleViewOutput},
+    tracks::{SUBTITLE_TRACKS, StreamIndex, SubtitleCue},
     transcript::{Transcript, TranscriptMsg, TranscriptOutput},
     util::OptionTracker,
 };
 
 pub struct App {
-    url: String,
     transcript: Controller<Transcript>,
     player: Controller<Player>,
     subtitle_view: Controller<SubtitleView>,
     extractor: WorkerController<SubtitleExtractor>,
+
     preferences: Controller<Preferences>,
+    open_url_dialog: Controller<OpenDialog>,
     subtitle_selection_dialog: Controller<SubtitleSelectionDialog>,
 
     primary_stream_ix: Option<StreamIndex>,
@@ -37,20 +38,24 @@ pub struct App {
 
 #[derive(Debug)]
 pub enum AppMsg {
-    NewOrUpdatedTrackMetadata(StreamIndex),
-    NewCue(StreamIndex, crate::subtitle_extractor::SubtitleCue),
+    NewCue(StreamIndex, SubtitleCue),
     SubtitleExtractionComplete,
     PrimarySubtitleTrackSelected(Option<StreamIndex>),
     SecondarySubtitleTrackSelected(Option<StreamIndex>),
     PositionUpdate(gst::ClockTime),
     SetHoveringSubtitleCue(bool),
+    ShowUrlOpenDialog,
     ShowPreferences,
     ShowSubtitleSelectionDialog,
+    Play {
+        url: String,
+        whisper_stream_index: Option<StreamIndex>,
+    },
 }
 
 #[relm4::component(pub)]
 impl SimpleComponent for App {
-    type Init = String;
+    type Init = ();
     type Input = AppMsg;
     type Output = ();
 
@@ -61,10 +66,13 @@ impl SimpleComponent for App {
             set_default_width: 800,
             set_default_height: 600,
 
-            #[name(toolbar_view)]
             adw::ToolbarView {
                 add_top_bar = &adw::HeaderBar {
                     pack_start = &gtk::Button {
+                        set_label: "Open...",
+                        connect_clicked => AppMsg::ShowUrlOpenDialog,
+                    },
+                    pack_end = &gtk::Button {
                         set_icon_name: "settings-symbolic",
                         connect_clicked => AppMsg::ShowPreferences,
                     }
@@ -86,7 +94,7 @@ impl SimpleComponent for App {
     }
 
     fn init(
-        url: Self::Init,
+        _init: Self::Init,
         root: Self::Root,
         sender: ComponentSender<Self>,
     ) -> ComponentParts<Self> {
@@ -112,9 +120,6 @@ impl SimpleComponent for App {
         let extractor = SubtitleExtractor::builder().detach_worker(()).forward(
             sender.input_sender(),
             |output| match output {
-                SubtitleExtractorOutput::NewOrUpdatedTrackMetadata(stream_index) => {
-                    AppMsg::NewOrUpdatedTrackMetadata(stream_index)
-                }
                 SubtitleExtractorOutput::NewCue(stream_index, cue) => {
                     AppMsg::NewCue(stream_index, cue)
                 }
@@ -123,6 +128,18 @@ impl SimpleComponent for App {
         );
 
         let preferences = Preferences::builder().launch(root.clone().into()).detach();
+        let open_url_dialog = OpenDialog::builder().launch(root.clone().into()).forward(
+            sender.input_sender(),
+            |output| match output {
+                OpenDialogOutput::Play {
+                    url,
+                    whisper_stream_index,
+                } => AppMsg::Play {
+                    url,
+                    whisper_stream_index,
+                },
+            },
+        );
         let subtitle_selection_dialog = SubtitleSelectionDialog::builder()
             .launch(root.clone().into())
             .forward(sender.input_sender(), |output| match output {
@@ -135,12 +152,13 @@ impl SimpleComponent for App {
             });
 
         let model = Self {
-            url: url.clone(), // TODO remove clone
             player,
             transcript,
             subtitle_view,
             extractor,
+
             preferences,
+            open_url_dialog,
             subtitle_selection_dialog,
 
             primary_stream_ix: None,
@@ -155,26 +173,14 @@ impl SimpleComponent for App {
 
         let widgets = view_output!();
 
-        model
-            .player
-            .sender()
-            .send(PlayerMsg::SetUrl(url.clone()))
-            .unwrap();
-        model
-            .extractor
-            .sender()
-            .send(SubtitleExtractorMsg::ExtractFromUrl(url))
-            .unwrap();
-
         ComponentParts { model, widgets }
     }
 
-    fn update(&mut self, msg: Self::Input, _sender: ComponentSender<Self>) {
+    fn update(&mut self, message: Self::Input, _sender: ComponentSender<Self>) {
         self.primary_last_cue_ix.reset();
         self.secondary_last_cue_ix.reset();
 
-        match msg {
-            AppMsg::NewOrUpdatedTrackMetadata(_stream_index) => {}
+        match message {
             AppMsg::NewCue(stream_index, cue) => {
                 self.transcript
                     .sender()
@@ -257,6 +263,12 @@ impl SimpleComponent for App {
                     self.autopaused = false;
                 }
             }
+            AppMsg::ShowUrlOpenDialog => {
+                self.open_url_dialog
+                    .sender()
+                    .send(OpenDialogMsg::Show)
+                    .unwrap();
+            }
             AppMsg::ShowPreferences => {
                 self.preferences
                     .sender()
@@ -269,6 +281,22 @@ impl SimpleComponent for App {
                     .send(SubtitleSelectionDialogMsg::Show)
                     .unwrap();
             }
+            AppMsg::Play {
+                url,
+                whisper_stream_index,
+            } => {
+                self.player
+                    .sender()
+                    .send(PlayerMsg::SetUrl(url.clone()))
+                    .unwrap();
+                self.extractor
+                    .sender()
+                    .send(SubtitleExtractorMsg::ExtractFromUrl {
+                        url,
+                        whisper_stream_index,
+                    })
+                    .unwrap();
+            }
         }
     }
 }
@@ -279,7 +307,7 @@ impl App {
         position: gst::ClockTime,
         last_cue_ix: &mut OptionTracker<usize>,
     ) -> Option<String> {
-        let lock = TRACKS.read();
+        let lock = SUBTITLE_TRACKS.read();
         let track = lock.get(&stream_ix)?;
 
         // try to find current cue quickly (should usually succeed during playback)