diff --git a/src/ass_file.cpp b/src/ass_file.cpp index 743bbfea2..7667da14f 100644 --- a/src/ass_file.cpp +++ b/src/ass_file.cpp @@ -202,6 +202,12 @@ bool AssFile::CompEffect(AssDialogue const& lft, AssDialogue const& rgt) { bool AssFile::CompLayer(AssDialogue const& lft, AssDialogue const& rgt) { return lft.Layer < rgt.Layer; } +bool AssFile::CompText(AssDialogue const& lft, AssDialogue const& rgt) { + return lft.Text < rgt.Text; +} +bool AssFile::CompTextStripped(AssDialogue const& lft, AssDialogue const& rgt) { + return lft.GetStrippedText() < rgt.GetStrippedText(); +} void AssFile::Sort(CompFunc comp, std::set const& limit) { Sort(Events, comp, limit); diff --git a/src/ass_file.h b/src/ass_file.h index bf5f39398..09cc0c09b 100644 --- a/src/ass_file.h +++ b/src/ass_file.h @@ -208,6 +208,10 @@ public: static bool CompEffect(AssDialogue const& lft, AssDialogue const& rgt); /// Compare based on layer static bool CompLayer(AssDialogue const& lft, AssDialogue const& rgt); + /// Compare based on text + static bool CompText(AssDialogue const& lft, AssDialogue const& rgt); + /// Compare based on stripped text + static bool CompTextStripped(AssDialogue const& lft, AssDialogue const& rgt); /// @brief Sort the dialogue lines in this file /// @param comp Comparison function to use. Defaults to sorting by start time. diff --git a/src/command/audio.cpp b/src/command/audio.cpp index a160e8eee..4872868cc 100644 --- a/src/command/audio.cpp +++ b/src/command/audio.cpp @@ -128,6 +128,17 @@ struct audio_open_video final : public Command { } }; +struct audio_reload final : public Command { + CMD_NAME("audio/reload") + STR_MENU("Reload Audio") + STR_DISP("Reload Audio") + STR_HELP("Reload the current audio file") + + void operator()(agi::Context *c) override { + c->project->ReloadAudio(); + } +}; + struct audio_view_spectrum final : public Command { CMD_NAME("audio/view/spectrum") STR_MENU("&Spectrum Display") @@ -549,6 +560,7 @@ namespace cmd { reg(agi::make_unique()); reg(agi::make_unique()); reg(agi::make_unique()); + reg(agi::make_unique()); reg(agi::make_unique()); reg(agi::make_unique()); reg(agi::make_unique()); diff --git a/src/command/grid.cpp b/src/command/grid.cpp index d591fd167..d65c6c364 100644 --- a/src/command/grid.cpp +++ b/src/command/grid.cpp @@ -249,6 +249,54 @@ struct grid_sort_style_selected final : public validate_sel_multiple { } }; +struct grid_sort_text final : public Command { + CMD_NAME("grid/sort/text") + STR_MENU("Te&xt") + STR_DISP("Text") + STR_HELP("Sort all subtitles by their text, including styling tags") + + void operator()(agi::Context *c) override { + c->ass->Sort(AssFile::CompText); + c->ass->Commit(_("sort"), AssFile::COMMIT_ORDER); + } +}; + +struct grid_sort_text_selected final : public validate_sel_multiple { + CMD_NAME("grid/sort/text/selected") + STR_MENU("Te&xt") + STR_DISP("Text") + STR_HELP("Sort selected subtitles by their text, including styling tags") + + void operator()(agi::Context *c) override { + c->ass->Sort(AssFile::CompText, c->selectionController->GetSelectedSet()); + c->ass->Commit(_("sort"), AssFile::COMMIT_ORDER); + } +}; + +struct grid_sort_text_stripped final : public Command { + CMD_NAME("grid/sort/text_stripped") + STR_MENU("Stri&pped Text") + STR_DISP("Stripped Text") + STR_HELP("Sort all subtitles by their stripped text") + + void operator()(agi::Context *c) override { + c->ass->Sort(AssFile::CompTextStripped); + c->ass->Commit(_("sort"), AssFile::COMMIT_ORDER); + } +}; + +struct grid_sort_text_stripped_selected final : public validate_sel_multiple { + CMD_NAME("grid/sort/text_stripped/selected") + STR_MENU("Stri&pped Text") + STR_DISP("Stripped Text") + STR_HELP("Sort selected subtitles by their stripped text") + + void operator()(agi::Context *c) override { + c->ass->Sort(AssFile::CompTextStripped, c->selectionController->GetSelectedSet()); + c->ass->Commit(_("sort"), AssFile::COMMIT_ORDER); + } +}; + struct grid_tag_cycle_hiding final : public Command { CMD_NAME("grid/tag/cycle_hiding") CMD_ICON(toggle_tag_hiding) @@ -529,12 +577,16 @@ namespace cmd { reg(agi::make_unique()); reg(agi::make_unique()); reg(agi::make_unique()); + reg(agi::make_unique()); + reg(agi::make_unique()); reg(agi::make_unique()); reg(agi::make_unique()); reg(agi::make_unique()); reg(agi::make_unique()); reg(agi::make_unique()); reg(agi::make_unique()); + reg(agi::make_unique()); + reg(agi::make_unique()); reg(agi::make_unique()); reg(agi::make_unique()); reg(agi::make_unique()); diff --git a/src/command/video.cpp b/src/command/video.cpp index 26ef06e21..1bfcc6e91 100644 --- a/src/command/video.cpp +++ b/src/command/video.cpp @@ -629,6 +629,17 @@ struct video_open_dummy final : public Command { } }; +struct video_reload final : public Command { + CMD_NAME("video/reload") + STR_MENU("Reload Video") + STR_DISP("Reload Video") + STR_HELP("Reload the current video file") + + void operator()(agi::Context *c) override { + c->project->ReloadVideo(); + } +}; + struct video_opt_autoscroll final : public Command { CMD_NAME("video/opt/autoscroll") CMD_ICON(toggle_video_autoscroll) @@ -823,6 +834,7 @@ namespace cmd { reg(agi::make_unique()); reg(agi::make_unique()); reg(agi::make_unique()); + reg(agi::make_unique()); reg(agi::make_unique()); reg(agi::make_unique()); reg(agi::make_unique()); diff --git a/src/libresrc/default_menu.json b/src/libresrc/default_menu.json index c566876e5..e6e1d1ba0 100644 --- a/src/libresrc/default_menu.json +++ b/src/libresrc/default_menu.json @@ -117,6 +117,8 @@ { "command" : "grid/sort/style" }, { "command" : "grid/sort/actor" }, { "command" : "grid/sort/effect" }, + { "command" : "grid/sort/text" }, + { "command" : "grid/sort/text_stripped" }, { "command" : "grid/sort/layer" } ], "main/subtitle/sort selected lines" : [ @@ -125,6 +127,8 @@ { "command" : "grid/sort/style/selected" }, { "command" : "grid/sort/actor/selected" }, { "command" : "grid/sort/effect/selected" }, + { "command" : "grid/sort/text/selected" }, + { "command" : "grid/sort/text_stripped/selected" }, { "command" : "grid/sort/layer/selected" } ], "main/timing" : [ diff --git a/src/libresrc/osx/default_menu.json b/src/libresrc/osx/default_menu.json index d61b2fd50..e47d3e634 100644 --- a/src/libresrc/osx/default_menu.json +++ b/src/libresrc/osx/default_menu.json @@ -119,6 +119,8 @@ { "command" : "grid/sort/style" }, { "command" : "grid/sort/actor" }, { "command" : "grid/sort/effect" }, + { "command" : "grid/sort/text" }, + { "command" : "grid/sort/text_stripped" }, { "command" : "grid/sort/layer" } ], "main/subtitle/sort selected lines" : [ @@ -127,6 +129,8 @@ { "command" : "grid/sort/style/selected" }, { "command" : "grid/sort/actor/selected" }, { "command" : "grid/sort/effect/selected" }, + { "command" : "grid/sort/text/selected" }, + { "command" : "grid/sort/text_stripped/selected" }, { "command" : "grid/sort/layer/selected" } ], "main/timing" : [ diff --git a/src/project.h b/src/project.h index 385a41b4b..090f99d3d 100644 --- a/src/project.h +++ b/src/project.h @@ -60,8 +60,6 @@ class Project { void LoadUnloadFiles(ProjectProperties properties); void UpdateRelativePaths(); - void ReloadAudio(); - void ReloadVideo(); void SetPath(agi::fs::path& var, const char *token, const char *mru, agi::fs::path const& value); @@ -74,11 +72,13 @@ public: bool CanLoadSubtitlesFromVideo() const { return video_has_subtitles; } void LoadAudio(agi::fs::path path); + void ReloadAudio(); void CloseAudio(); agi::AudioProvider *AudioProvider() const { return audio_provider.get(); } agi::fs::path const& AudioName() const { return audio_file; } void LoadVideo(agi::fs::path path); + void ReloadVideo(); void CloseVideo(); AsyncVideoProvider *VideoProvider() const { return video_provider.get(); } agi::fs::path const& VideoName() const { return video_file; } diff --git a/src/subtitle_format_ass.cpp b/src/subtitle_format_ass.cpp index 9117897ab..97fe61060 100644 --- a/src/subtitle_format_ass.cpp +++ b/src/subtitle_format_ass.cpp @@ -108,21 +108,20 @@ struct Writer { WriteIfNotZero("Scroll Position: ", properties.scroll_position); WriteIfNotZero("Active Line: ", properties.active_row); WriteIfNotZero("Video Position: ", properties.video_position); - - std::string foldsdata; - for (LineFold fold : properties.folds) { - if (!foldsdata.empty()) { - foldsdata += ","; - } - foldsdata += std::to_string(fold.start); - foldsdata += ":"; - foldsdata += std::to_string(fold.end); - foldsdata += ":"; - foldsdata += fold.collapsed ? "1" : "0"; - } - - WriteIfNotEmpty("Line Folds: ", foldsdata); } + + std::string foldsdata; + for (LineFold fold : properties.folds) { + if (!foldsdata.empty()) { + foldsdata += ","; + } + foldsdata += std::to_string(fold.start); + foldsdata += ":"; + foldsdata += std::to_string(fold.end); + foldsdata += ":"; + foldsdata += fold.collapsed ? "1" : "0"; + } + WriteIfNotEmpty("Line Folds: ", foldsdata); } void WriteIfNotEmpty(const char *key, std::string const& value) { diff --git a/src/video_provider_manager.cpp b/src/video_provider_manager.cpp index c239163b8..917b923d5 100644 --- a/src/video_provider_manager.cpp +++ b/src/video_provider_manager.cpp @@ -51,7 +51,7 @@ namespace { {"Avisynth", CreateAvisynthVideoProvider, false}, #endif #ifdef WITH_BESTSOURCE - {"BestSource", CreateBSVideoProvider, false}, + {"BestSource (SLOW)", CreateBSVideoProvider, false}, #endif #ifdef WITH_VAPOURSYNTH {"Vapoursynth", CreateVapoursynthVideoProvider, false},