1 /*
2    mkvmerge -- utility for splicing together matroska files
3    from component media subtypes
4 
5    Distributed under the GPL v2
6    see the file COPYING for details
7    or visit https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
8 
9    definition of functions helping dealing with tags
10 
11    Written by Moritz Bunkus <moritz@bunkus.org>.
12 */
13 
14 #pragma once
15 
16 #include "common/common_pch.h"
17 
18 #include "common/bcp47.h"
19 #include "common/ebml.h"
20 #include "common/strings/utf8.h"
21 #include "common/tags/target_type.h"
22 
23 namespace libmatroska {
24   class KaxTags;
25   class KaxTag;
26   class KaxTagSimple;
27   class KaxChapters;
28 }
29 
30 namespace libebml {
31   class EbmlElement;
32   class EbmlMaster;
33 }
34 
35 namespace mtx::tags {
36 
37 void remove_track_uid_targets(libebml::EbmlMaster *tag);
38 void remove_elements_unsupported_by_webm(libebml::EbmlMaster &master);
39 bool remove_track_statistics(libmatroska::KaxTags *tags, std::optional<uint64_t> track_uid);
40 
41 libmatroska::KaxTags *select_for_chapters(libmatroska::KaxTags &tags, libmatroska::KaxChapters &chapters);
42 
43 libmatroska::KaxTagSimple &find_simple(const std::string &name, libebml::EbmlMaster &m);
44 libmatroska::KaxTagSimple &find_simple(const UTFstring &name, libebml::EbmlMaster &m);
45 std::string get_simple_value(const std::string &name, libebml::EbmlMaster &m);
46 int64_t get_tuid(const libmatroska::KaxTag &tag);
47 int64_t get_cuid(const libmatroska::KaxTag &tag);
48 
49 std::string get_simple_name(const libmatroska::KaxTagSimple &tag);
50 std::string get_simple_value(const libmatroska::KaxTagSimple &tag);
51 
52 void set_simple_name(libmatroska::KaxTagSimple &tag, const std::string &name);
53 void set_simple_value(libmatroska::KaxTagSimple &tag, const std::string &value);
54 void set_simple(libmatroska::KaxTagSimple &tag, const std::string &name, const std::string &value);
55 void set_simple(libmatroska::KaxTag &tag, std::string const &name, std::string const &value, mtx::bcp47::language_c const &language = {});
56 void set_target_type(libmatroska::KaxTag &tag, target_type_e target_type_value, std::string const &target_type);
57 
58 int count_simple(libebml::EbmlMaster &master);
59 
60 void convert_old(libmatroska::KaxTags &tags);
61 
62 template<typename T>
63 bool
remove_simple_tags_for(libmatroska::KaxTags & tags,std::optional<uint64_t> id,std::string const & name_to_remove)64 remove_simple_tags_for(libmatroska::KaxTags &tags,
65                        std::optional<uint64_t> id,
66                        std::string const &name_to_remove) {
67   auto removed_something = false;
68   auto tag_idx = 0u;
69   while (tag_idx < tags.ListSize()) {
70     auto tag = dynamic_cast<libmatroska::KaxTag *>(tags[tag_idx]);
71     if (!tag) {
72       ++tag_idx;
73       continue;
74     }
75 
76     if (id) {
77       auto targets   = FindChild<libmatroska::KaxTagTargets>(*tag);
78       auto actual_id = targets ? std::optional<uint64_t>{ FindChildValue<T>(*targets, 0llu) } : std::optional<uint64_t>{ std::nullopt };
79 
80       if (!targets || !actual_id || (*actual_id != *id)) {
81         ++tag_idx;
82         continue;
83       }
84     }
85 
86     auto simple_idx = 0u;
87     while (simple_idx < tag->ListSize()) {
88       auto simple = dynamic_cast<libmatroska::KaxTagSimple *>((*tag)[simple_idx]);
89       if (!simple || (to_utf8(get_simple_name(*simple)) != name_to_remove))
90         ++simple_idx;
91 
92       else {
93         tag->Remove(simple_idx);
94         delete simple;
95         removed_something = true;
96       }
97     }
98 
99     if (0 < count_simple(*tag))
100       ++tag_idx;
101 
102     else {
103       tags.Remove(tag_idx);
104       delete tag;
105       removed_something = true;
106     }
107   }
108 
109   return removed_something;
110 }
111 
112 std::shared_ptr<libmatroska::KaxTags> merge(std::shared_ptr<libmatroska::KaxTags> const &t1, std::shared_ptr<libmatroska::KaxTags> const &t2);
113 
114 }
115