From c494170054f4a7f78ce14578651c60ac55537aad Mon Sep 17 00:00:00 2001 From: Moritz Bunkus Date: Sat, 19 Dec 2015 14:28:39 +0100 Subject: [PATCH] mkvpropedit: add option for removing statistics tags for all tracks Part of the implementation of #1507. --- ChangeLog | 4 ++++ src/propedit/options.cpp | 5 ++++ src/propedit/options.h | 3 ++- src/propedit/propedit.cpp | 27 +++++++++++++++++---- src/propedit/propedit_cli_parser.cpp | 7 ++++++ src/propedit/propedit_cli_parser.h | 2 ++ src/propedit/tag_target.cpp | 35 ++++++++++++++++++++++++++-- src/propedit/tag_target.h | 6 +++++ src/propedit/target.cpp | 6 +++++ src/propedit/target.h | 1 + 10 files changed, 89 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0b21186ab..12d49eaf2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2015-12-19 Moritz Bunkus + * mkvpropedit: new feature: added an option for removing all + existing track statistics tags from a file. Part of the + implementation of #1507. + * mkvmerge: bug fix: AAC with low sampling frequencies was sometimes mis-detected with the wrong profile preventing appending it to other AAC tracks. Fixes #1540. diff --git a/src/propedit/options.cpp b/src/propedit/options.cpp index 70170d348..f499bbd0b 100644 --- a/src/propedit/options.cpp +++ b/src/propedit/options.cpp @@ -95,6 +95,11 @@ options_c::add_attachment_command(attachment_target_c::command_e command, m_targets.push_back(target); } +void +options_c::add_delete_track_statistics_tags(tag_target_c::tag_operation_mode_e operation_mode) { + m_targets.push_back(std::make_shared(operation_mode)); +} + void options_c::set_file_name(const std::string &file_name) { if (!m_file_name.empty()) diff --git a/src/propedit/options.h b/src/propedit/options.h index c4e16af1f..17ec7ce54 100644 --- a/src/propedit/options.h +++ b/src/propedit/options.h @@ -17,7 +17,7 @@ #include "common/kax_analyzer.h" #include "propedit/attachment_target.h" -#include "propedit/target.h" +#include "propedit/tag_target.h" class options_c { public: @@ -36,6 +36,7 @@ public: void add_tags(const std::string &spec); void add_chapters(const std::string &spec); void add_attachment_command(attachment_target_c::command_e command, std::string const &spec, attachment_target_c::options_t const &options); + void add_delete_track_statistics_tags(tag_target_c::tag_operation_mode_e operation_mode); void set_file_name(const std::string &file_name); void set_parse_mode(const std::string &parse_mode); void dump_info() const; diff --git a/src/propedit/propedit.cpp b/src/propedit/propedit.cpp index 4b71eb021..42e562d95 100644 --- a/src/propedit/propedit.cpp +++ b/src/propedit/propedit.cpp @@ -47,6 +47,22 @@ display_update_element_result(const EbmlCallbacks &callbacks, mxerror(message + "\n"); } +namespace mtx { + +template bool +any(Trange range, + Tpredicate predicate) { + return boost::range::find_if(range, predicate) != boost::end(range); +} + +} + +bool +has_content_been_modified(options_cptr const &options) { + return mtx::any(options->m_targets, [](target_cptr const &t) { return t->has_content_been_modified(); }); +} + static void write_changes(options_cptr &options, kax_analyzer_c *analyzer) { @@ -120,11 +136,15 @@ run(options_cptr &options) { options->execute(); - mxinfo(Y("The changes are written to the file.\n")); + if (has_content_been_modified(options)) { + mxinfo(Y("The changes are written to the file.\n")); - write_changes(options, analyzer.get()); + write_changes(options, analyzer.get()); - mxinfo(Y("Done.\n")); + mxinfo(Y("Done.\n")); + + } else + mxinfo(Y("No changes were made.\n")); mxexit(); } @@ -136,7 +156,6 @@ void setup(char **argv) { version_info = get_version_info("mkvpropedit", vif_full); } - /** \brief Setup and high level program control Calls the functions for setup, handling the command line arguments, diff --git a/src/propedit/propedit_cli_parser.cpp b/src/propedit/propedit_cli_parser.cpp index 547547868..9591cacdd 100644 --- a/src/propedit/propedit_cli_parser.cpp +++ b/src/propedit/propedit_cli_parser.cpp @@ -127,6 +127,11 @@ propedit_cli_parser_c::replace_attachment() { } } +void +propedit_cli_parser_c::handle_track_statistics_tags() { + m_options->add_delete_track_statistics_tags(m_current_arg == "--add-track-statistics-tags" ? tag_target_c::tom_add_track_statistics : tag_target_c::tom_delete_track_statistics); +} + std::map & propedit_cli_parser_c::get_ebml_type_abbrev_map() { static std::map s_ebml_type_abbrevs; @@ -216,6 +221,8 @@ propedit_cli_parser_c::init_parser() { "(see below and man page for syntax)")); OPT("c|chapters=", add_chapters, YT("Add or replace chapters in the file with the ones from 'filename' " "or remove them if 'filename' is empty")); + // OPT("add-track-statistics-tags", handle_track_statistics_tags, YT("Calculate statistics for all tracks and add new/update existing tags for them")); + OPT("delete-track-statistics-tags", handle_track_statistics_tags, YT("Delete all existing track statistics tags")); add_section_header(YT("Actions for handling attachments")); OPT("add-attachment=", add_attachment, YT("Add the file 'filename' as a new attachment")); diff --git a/src/propedit/propedit_cli_parser.h b/src/propedit/propedit_cli_parser.h index fb7f1efdb..4dbf479d1 100644 --- a/src/propedit/propedit_cli_parser.h +++ b/src/propedit/propedit_cli_parser.h @@ -50,6 +50,8 @@ protected: void list_property_names(); void list_property_names_for_table(const std::vector &table, const std::string &title, const std::string &edit_spec); + void handle_track_statistics_tags(); + std::map &get_ebml_type_abbrev_map(); }; diff --git a/src/propedit/tag_target.cpp b/src/propedit/tag_target.cpp index d2d66a745..1d4aafa8f 100644 --- a/src/propedit/tag_target.cpp +++ b/src/propedit/tag_target.cpp @@ -13,6 +13,7 @@ #include #include +#include "common/list_utils.h" #include "common/output.h" #include "common/strings/editing.h" #include "common/strings/parsing.h" @@ -28,6 +29,12 @@ tag_target_c::tag_target_c() { } +tag_target_c::tag_target_c(tag_operation_mode_e operation_mode) + : track_target_c{""} + , m_operation_mode{operation_mode} +{ +} + tag_target_c::~tag_target_c() { } @@ -45,6 +52,9 @@ tag_target_c::operator ==(target_c const &cmp) void tag_target_c::validate() { + if (mtx::included_in(m_operation_mode, tom_add_track_statistics, tom_delete_track_statistics)) + return; + if (!m_file_name.empty() && !m_new_tags) m_new_tags = mtx::xml::ebml_tags_converter_c::parse_file(m_file_name, false); } @@ -103,8 +113,7 @@ tag_target_c::has_changes() bool tag_target_c::non_track_target() const { - return (tom_all == m_operation_mode) - || (tom_global == m_operation_mode); + return mtx::included_in(m_operation_mode, tom_all, tom_global, tom_add_track_statistics, tom_delete_track_statistics); } bool @@ -130,6 +139,9 @@ tag_target_c::execute() { else if (tom_track == m_operation_mode) add_or_replace_track_tags(m_new_tags.get()); + else if (tom_delete_track_statistics == m_operation_mode) + delete_track_statistics_tags(); + else assert(false); @@ -151,6 +163,8 @@ tag_target_c::add_or_replace_global_tags(KaxTags *tags) { delete tag; m_level1_element->Remove(idx); } + + m_tags_modified = true; } if (tags) { @@ -163,6 +177,8 @@ tag_target_c::add_or_replace_global_tags(KaxTags *tags) { m_level1_element->PushElement(*tag); tags->Remove(idx); } + + m_tags_modified = true; } } } @@ -180,6 +196,8 @@ tag_target_c::add_or_replace_track_tags(KaxTags *tags) { delete tag; m_level1_element->Remove(idx); } + + m_tags_modified = true; } if (tags) { @@ -195,6 +213,19 @@ tag_target_c::add_or_replace_track_tags(KaxTags *tags) { m_level1_element->PushElement(*tag); tags->Remove(idx); } + + m_tags_modified = true; } } } + +void +tag_target_c::delete_track_statistics_tags() { + m_tags_modified = mtx::tags::remove_track_statistics(static_cast(m_level1_element), boost::none); +} + +bool +tag_target_c::has_content_been_modified() + const { + return m_tags_modified; +} diff --git a/src/propedit/tag_target.h b/src/propedit/tag_target.h index cd52c25f0..7266a09c7 100644 --- a/src/propedit/tag_target.h +++ b/src/propedit/tag_target.h @@ -26,13 +26,17 @@ public: tom_all, tom_global, tom_track, + tom_add_track_statistics, + tom_delete_track_statistics, }; tag_operation_mode_e m_operation_mode; std::shared_ptr m_new_tags; + bool m_tags_modified{}; public: tag_target_c(); + tag_target_c(tag_operation_mode_e operation_mode); virtual ~tag_target_c(); virtual void validate(); @@ -42,12 +46,14 @@ public: virtual void dump_info() const; virtual bool has_changes() const; + virtual bool has_content_been_modified() const override; virtual void execute(); protected: virtual void add_or_replace_global_tags(KaxTags *tags); virtual void add_or_replace_track_tags(KaxTags *tags); + virtual void delete_track_statistics_tags(); virtual bool non_track_target() const; virtual bool sub_master_is_track() const; diff --git a/src/propedit/target.cpp b/src/propedit/target.cpp index d3cc27ff7..e9bcf2729 100644 --- a/src/propedit/target.cpp +++ b/src/propedit/target.cpp @@ -90,3 +90,9 @@ target_c::get_level1_element() const { return m_level1_element; } + +bool +target_c::has_content_been_modified() + const { + return true; +} diff --git a/src/propedit/target.h b/src/propedit/target.h index dff4e88a5..83d7712d5 100644 --- a/src/propedit/target.h +++ b/src/propedit/target.h @@ -49,6 +49,7 @@ public: virtual void set_level1_element(ebml_element_cptr level1_element, ebml_element_cptr track_headers = ebml_element_cptr{}); virtual bool has_changes() const = 0; + virtual bool has_content_been_modified() const; virtual void execute() = 0;