diff options
Diffstat (limited to 'src/app.rs')
-rw-r--r-- | src/app.rs | 146 |
1 files changed, 49 insertions, 97 deletions
diff --git a/src/app.rs b/src/app.rs index 10c20e6..18f03e8 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,6 +1,4 @@ use adw::prelude::*; -use gst::glib::clone; -use gtk::gio::{Menu, MenuItem, SimpleAction, SimpleActionGroup}; use relm4::{WorkerController, prelude::*}; use crate::{ @@ -9,13 +7,14 @@ use crate::{ subtitle_extractor::{ StreamIndex, SubtitleExtractor, SubtitleExtractorMsg, SubtitleExtractorOutput, TRACKS, }, + subtitle_selection_dialog::{ + SubtitleSelectionDialog, SubtitleSelectionDialogMsg, SubtitleSelectionDialogOutput, + }, subtitle_view::{SubtitleView, SubtitleViewMsg, SubtitleViewOutput}, transcript::{Transcript, TranscriptMsg, TranscriptOutput}, util::OptionTracker, }; -const TRACK_SELECTION_ACTION_GROUP_NAME: &str = "subtitle_track_selection"; - pub struct App { url: String, transcript: Controller<Transcript>, @@ -23,9 +22,7 @@ pub struct App { subtitle_view: Controller<SubtitleView>, extractor: WorkerController<SubtitleExtractor>, preferences: Controller<Preferences>, - - subtitle_selection_menu: Menu, - subtitle_selection_action_group: SimpleActionGroup, + subtitle_selection_dialog: Controller<SubtitleSelectionDialog>, primary_stream_ix: Option<StreamIndex>, primary_last_cue_ix: OptionTracker<usize>, @@ -42,11 +39,13 @@ pub struct App { pub enum AppMsg { NewOrUpdatedTrackMetadata(StreamIndex), NewCue(StreamIndex, crate::subtitle_extractor::SubtitleCue), - ExtractionComplete, - TrackSelected(StreamIndex), + SubtitleExtractionComplete, + PrimarySubtitleTrackSelected(Option<StreamIndex>), + SecondarySubtitleTrackSelected(Option<StreamIndex>), PositionUpdate(gst::ClockTime), SetHoveringSubtitleCue(bool), ShowPreferences, + ShowSubtitleSelectionDialog, } #[relm4::component(pub)] @@ -65,14 +64,9 @@ impl SimpleComponent for App { #[name(toolbar_view)] adw::ToolbarView { add_top_bar = &adw::HeaderBar { - pack_start = >k::MenuButton { - set_label: "Select Subtitle Track", - set_popover: Some(>k::PopoverMenu::from_model(Some(&model.subtitle_selection_menu))), - }, pack_start = >k::Button { - set_label: "Preferences", + set_icon_name: "settings-symbolic", connect_clicked => AppMsg::ShowPreferences, - add_css_class: "flat", } }, @@ -96,14 +90,6 @@ impl SimpleComponent for App { root: Self::Root, sender: ComponentSender<Self>, ) -> ComponentParts<Self> { - let subtitle_selection_menu = Menu::new(); - let subtitle_selection_action_group = SimpleActionGroup::new(); - root.insert_action_group( - TRACK_SELECTION_ACTION_GROUP_NAME, - Some(&subtitle_selection_action_group), - ); - Self::add_dummy_menu_item(&subtitle_selection_action_group, &subtitle_selection_menu); - let subtitle_view = SubtitleView::builder().launch(()).forward( sender.input_sender(), |output| match output { @@ -114,6 +100,7 @@ impl SimpleComponent for App { .launch(()) .forward(sender.input_sender(), |output| match output { PlayerOutput::PositionUpdate(pos) => AppMsg::PositionUpdate(pos), + PlayerOutput::SubtitleSelectionButtonPressed => AppMsg::ShowSubtitleSelectionDialog, }); let transcript = Transcript::builder() @@ -131,11 +118,21 @@ impl SimpleComponent for App { SubtitleExtractorOutput::NewCue(stream_index, cue) => { AppMsg::NewCue(stream_index, cue) } - SubtitleExtractorOutput::ExtractionComplete => AppMsg::ExtractionComplete, + SubtitleExtractorOutput::ExtractionComplete => AppMsg::SubtitleExtractionComplete, }, ); let preferences = Preferences::builder().launch(root.clone().into()).detach(); + let subtitle_selection_dialog = SubtitleSelectionDialog::builder() + .launch(root.clone().into()) + .forward(sender.input_sender(), |output| match output { + SubtitleSelectionDialogOutput::PrimaryTrackSelected(ix) => { + AppMsg::PrimarySubtitleTrackSelected(ix) + } + SubtitleSelectionDialogOutput::SecondaryTrackSelected(ix) => { + AppMsg::SecondarySubtitleTrackSelected(ix) + } + }); let model = Self { url: url.clone(), // TODO remove clone @@ -144,8 +141,7 @@ impl SimpleComponent for App { subtitle_view, extractor, preferences, - subtitle_selection_menu, - subtitle_selection_action_group, + subtitle_selection_dialog, primary_stream_ix: None, primary_last_cue_ix: OptionTracker::new(None), @@ -173,31 +169,32 @@ impl SimpleComponent for App { ComponentParts { model, widgets } } - fn update(&mut self, msg: Self::Input, sender: ComponentSender<Self>) { + fn update(&mut self, msg: Self::Input, _sender: ComponentSender<Self>) { self.primary_last_cue_ix.reset(); self.secondary_last_cue_ix.reset(); match msg { - AppMsg::NewOrUpdatedTrackMetadata(_stream_index) => { - self.update_subtitle_selection_menu(&sender); - } + AppMsg::NewOrUpdatedTrackMetadata(_stream_index) => {} AppMsg::NewCue(stream_index, cue) => { self.transcript .sender() .send(TranscriptMsg::NewCue(stream_index, cue)) .unwrap(); } - AppMsg::ExtractionComplete => { - println!("Subtitle extraction complete"); + AppMsg::SubtitleExtractionComplete => { + log::info!("Subtitle extraction complete"); } - AppMsg::TrackSelected(stream_index) => { - self.primary_stream_ix = Some(stream_index); + AppMsg::PrimarySubtitleTrackSelected(stream_index) => { + self.primary_stream_ix = stream_index; self.transcript .sender() .send(TranscriptMsg::SelectTrack(stream_index)) .unwrap(); } + AppMsg::SecondarySubtitleTrackSelected(stream_index) => { + self.secondary_stream_ix = stream_index; + } AppMsg::PositionUpdate(pos) => { if let Some(stream_ix) = self.primary_stream_ix { let cue = @@ -239,14 +236,18 @@ impl SimpleComponent for App { } } if let Some(stream_ix) = self.secondary_stream_ix { - self.subtitle_view - .sender() - .send(SubtitleViewMsg::SetPrimaryCue(Self::get_cue_and_update_ix( - stream_ix, - pos, - &mut self.primary_last_cue_ix, - ))) - .unwrap(); + if !self.autopaused { + self.subtitle_view + .sender() + .send(SubtitleViewMsg::SetSecondaryCue( + Self::get_cue_and_update_ix( + stream_ix, + pos, + &mut self.secondary_last_cue_ix, + ), + )) + .unwrap(); + } } } AppMsg::SetHoveringSubtitleCue(hovering) => { @@ -262,66 +263,17 @@ impl SimpleComponent for App { .send(PreferencesMsg::Show) .unwrap(); } + AppMsg::ShowSubtitleSelectionDialog => { + self.subtitle_selection_dialog + .sender() + .send(SubtitleSelectionDialogMsg::Show) + .unwrap(); + } } } } impl App { - fn update_subtitle_selection_menu(&mut self, sender: &ComponentSender<Self>) { - self.subtitle_selection_menu.remove_all(); - - for action_name in self.subtitle_selection_action_group.list_actions() { - self.subtitle_selection_action_group - .remove_action(&action_name); - } - - let tracks = TRACKS.read(); - if tracks.is_empty() { - Self::add_dummy_menu_item( - &self.subtitle_selection_action_group, - &self.subtitle_selection_menu, - ); - } else { - for (stream_index, track) in tracks.iter() { - let unknown_string = "<unknown>".to_string(); - let language = track.language_code.as_ref().unwrap_or(&unknown_string); - let label = format!("{} (Stream {})", language, stream_index); - - let action_name = format!("select_{}", stream_index); - let action = SimpleAction::new(&action_name, None); - - action.connect_activate(clone!( - #[strong] - sender, - #[strong] - stream_index, - move |_, _| { - let _ = sender.input(AppMsg::TrackSelected(stream_index)); - } - )); - - self.subtitle_selection_action_group.add_action(&action); - - // Create menu item - let action_target = - format!("{}.{}", TRACK_SELECTION_ACTION_GROUP_NAME, action_name); - let item = MenuItem::new(Some(&label), Some(&action_target)); - self.subtitle_selection_menu.append_item(&item); - } - } - } - - // Add disabled "No tracks available" item - fn add_dummy_menu_item(action_group: &SimpleActionGroup, menu: &Menu) { - let disabled_action = SimpleAction::new("no_tracks", None); - disabled_action.set_enabled(false); - action_group.add_action(&disabled_action); - - let action_target = format!("{}.no_tracks", TRACK_SELECTION_ACTION_GROUP_NAME); - let item = MenuItem::new(Some("No tracks available"), Some(&action_target)); - menu.append_item(&item); - } - fn get_cue_and_update_ix( stream_ix: StreamIndex, position: gst::ClockTime, |