diff --git a/src/common/tag_common.cpp b/src/common/tag_common.cpp new file mode 100644 index 000000000..9a25a3336 --- /dev/null +++ b/src/common/tag_common.cpp @@ -0,0 +1,280 @@ +/* + * mkvmerge -- utility for splicing together matroska files + * from component media subtypes + * + * Distributed under the GPL + * see the file COPYING for details + * or visit http://www.gnu.org/copyleft/gpl.html + * + * $Id$ + * + * tag helper functions + * + * Written by Moritz Bunkus . + */ + +#include +#include +#include +#include +#include + +#include +#include + +#include "chapters.h" +#include "common.h" +#include "commonebml.h" +#include "matroska.h" +#include "tag_common.h" + +#include +#include + +using namespace std; +using namespace libebml; +using namespace libmatroska; + +void +fix_mandatory_tag_elements(EbmlElement *e) { + if (dynamic_cast(e) != NULL) { + KaxTagSimple &s = *static_cast(e); + GetChild(s); + GetChild(s); + + } else if (dynamic_cast(e) != NULL) { + KaxTagTargets &t = *static_cast(e); + GetChild(t); + + } + + if (dynamic_cast(e) != NULL) { + EbmlMaster *m; + int i; + + m = static_cast(e); + for (i = 0; i < m->ListSize(); i++) + fix_mandatory_tag_elements((*m)[i]); + } +} + +KaxTags * +select_tags_for_chapters(KaxTags &tags, + KaxChapters &chapters) { + KaxTags *new_tags; + KaxTagTargets *targets; + KaxTagEditionUID *t_euid; + KaxTagChapterUID *t_cuid; + int tags_idx, targets_idx; + bool copy; + + new_tags = NULL; + for (tags_idx = 0; tags_idx < tags.ListSize(); tags_idx++) { + if (dynamic_cast(tags[tags_idx]) == NULL) + continue; + copy = true; + targets = FINDFIRST(static_cast(tags[tags_idx]), + KaxTagTargets); + if (targets != NULL) { + for (targets_idx = 0; targets_idx < targets->ListSize(); targets_idx++) { + t_euid = dynamic_cast((*targets)[targets_idx]); + if ((t_euid != NULL) && + (find_edition_with_uid(chapters, uint64(*t_euid)) == NULL)) { + copy = false; + break; + } + t_cuid = dynamic_cast((*targets)[targets_idx]); + if ((t_cuid != NULL) && + (find_chapter_with_uid(chapters, uint64(*t_cuid)) == NULL)) { + copy = false; + break; + } + } + } + + if (copy) { + if (new_tags == NULL) + new_tags = new KaxTags; + new_tags->PushElement(*(tags[tags_idx]->Clone())); + } + } + + return new_tags; +} + +KaxTagSimple & +find_simple_tag(const string &name, + EbmlMaster &m) { + return find_simple_tag(cstrutf8_to_UTFstring(name), m); +} + +KaxTagSimple & +find_simple_tag(const UTFstring &name, + EbmlMaster &m) { + int i; + string rvalue; + + if (EbmlId(m) == KaxTagSimple::ClassInfos.GlobalId) { + KaxTagName *tname; + + tname = FINDFIRST(&m, KaxTagName); + if ((tname != NULL) && + (name == UTFstring(*static_cast(tname)))) + return *static_cast(&m); + } + + for (i = 0; i < m.ListSize(); i++) + if ((EbmlId(*m[i]) == KaxTag::ClassInfos.GlobalId) || + (EbmlId(*m[i]) == KaxTagSimple::ClassInfos.GlobalId)) { + try { + return find_simple_tag(name, *static_cast(m[i])); + } catch (...) { + } + } + + throw ""; +} + +string +get_simple_tag_value(const string &name, + EbmlMaster &m) { + try { + KaxTagSimple &simple = find_simple_tag(name, m); + KaxTagString *tvalue; + + tvalue = FINDFIRST(&simple, KaxTagString); + if (tvalue != NULL) + return UTFstring_to_cstrutf8(UTFstring(*static_cast + (tvalue))); + } catch (...) { + } + + return ""; +} + +string +get_simple_tag_name(const KaxTagSimple &tag) { + KaxTagName *tname; + + tname = FINDFIRST(&tag, KaxTagName); + if (tname == NULL) + return ""; + return UTFstring_to_cstrutf8(UTFstring(*static_cast + (tname))); +} + +string +get_simple_tag_value(const KaxTagSimple &tag) { + KaxTagString *tstring; + + tstring = FINDFIRST(&tag, KaxTagString); + if (tstring == NULL) + return ""; + return UTFstring_to_cstrutf8(UTFstring(*static_cast + (tstring))); +} + +void +set_simple_tag_name(KaxTagSimple &tag, + const string &name) { + *static_cast(&GetChild(tag)) = + cstrutf8_to_UTFstring(name); +} + +void +set_simple_tag_value(KaxTagSimple &tag, + const string &value) { + *static_cast(&GetChild(tag)) = + cstrutf8_to_UTFstring(value); +} + +void +set_simple_tag(KaxTagSimple &tag, + const string &name, + const string &value) { + set_simple_tag_name(tag, name); + set_simple_tag_value(tag, value); +} + +int64_t +get_tag_tuid(const KaxTag &tag) { + KaxTagTargets *targets; + KaxTagTrackUID *tuid; + + targets = FINDFIRST(&tag, KaxTagTargets); + if (targets == NULL) + return -1; + tuid = FINDFIRST(targets, KaxTagTrackUID); + if (tuid == NULL) + return -1; + return uint64(*static_cast(tuid)); +} + +int64_t +get_tag_cuid(const KaxTag &tag) { + KaxTagTargets *targets; + KaxTagChapterUID *cuid; + + targets = FINDFIRST(&tag, KaxTagTargets); + if (targets == NULL) + return -1; + cuid = FINDFIRST(targets, KaxTagChapterUID); + if (cuid == NULL) + return -1; + return uint64(*static_cast(cuid)); +} + +/** \brief Convert older tags to current specs + */ +void +convert_old_tags(KaxTags &tags) { + string name, value; + int i, tags_idx, target_type_value; + bool has_level_type; + + try { + find_simple_tag("LEVEL_TYPE", tags); + has_level_type = true; + } catch (...) { + has_level_type = false; + } + + for (tags_idx = 0; tags_idx < tags.ListSize(); tags_idx++) { + if (!is_id(tags[tags_idx], KaxTag)) + continue; + KaxTag &tag = *static_cast(tags[tags_idx]); + + target_type_value = TAG_TARGETTYPE_TRACK; + i = 0; + while (i < tag.ListSize()) { + i++; + if (!is_id(tag[i - 1], KaxTagSimple)) + continue; + KaxTagSimple &simple = *static_cast(tag[i - 1]); + + name = get_simple_tag_name(simple); + value = get_simple_tag_value(simple); + + if (name == "CATALOG") + set_simple_tag_name(simple, "CATALOG_NUMBER"); + else if (name == "DATE") + set_simple_tag_name(simple, "DATE_RELEASED"); + else if (name == "LEVEL_TYPE") { + if (value == "MEDIA") + target_type_value = TAG_TARGETTYPE_ALBUM; + i--; + delete tag[i]; + tag.Remove(i); + } + } + + if (has_level_type) { + KaxTagTargets *targets; + + targets = FINDFIRST(&tag, KaxTagTargets); + if (targets != NULL) + *static_cast + (&GetChild(*targets)) = target_type_value; + } + } +} diff --git a/src/common/tag_common.h b/src/common/tag_common.h new file mode 100644 index 000000000..434099269 --- /dev/null +++ b/src/common/tag_common.h @@ -0,0 +1,61 @@ +/* + * mkvmerge -- utility for splicing together matroska files + * from component media subtypes + * + * Distributed under the GPL + * see the file COPYING for details + * or visit http://www.gnu.org/copyleft/gpl.html + * + * $Id$ + * + * definition of functions helping dealing with tags + * + * Written by Moritz Bunkus . + */ + +#ifndef __TAG_COMMON_H +#define __TAG_COMMON_H + +#include "os.h" + +#include + +namespace libmatroska { + class KaxTags; + class KaxTag; + class KaxTagSimple; + class KaxChapters; +}; + +namespace libebml { + class EbmlElement; + class EbmlMaster; +}; + +using namespace std; +using namespace libebml; +using namespace libmatroska; + +void MTX_DLL_API fix_mandatory_tag_elements(EbmlElement *e); + +KaxTags *MTX_DLL_API select_tags_for_chapters(KaxTags &tags, + KaxChapters &chapters); + +KaxTagSimple &MTX_DLL_API find_simple_tag(const string &name, EbmlMaster &m); +KaxTagSimple &MTX_DLL_API find_simple_tag(const UTFstring &name, + EbmlMaster &m); +string MTX_DLL_API get_simple_tag_value(const string &name, EbmlMaster &m); +int64_t MTX_DLL_API get_tag_tuid(const KaxTag &tag); +int64_t MTX_DLL_API get_tag_cuid(const KaxTag &tag); + +string MTX_DLL_API get_simple_tag_name(const KaxTagSimple &tag); +string MTX_DLL_API get_simple_tag_value(const KaxTagSimple &tag); + +void MTX_DLL_API set_simple_tag_name(KaxTagSimple &tag, const string &name); +void MTX_DLL_API set_simple_tag_value(KaxTagSimple &tag, const string &value); +void MTX_DLL_API set_simple_tag(KaxTagSimple &tag, const string &name, + const string &valuevalue); + +void MTX_DLL_API convert_old_tags(KaxTags &tags); + +#endif // __TAG_COMMON_H diff --git a/src/common/tagparser.cpp b/src/common/tagparser.cpp index 4257dd5f3..ac606e6df 100644 --- a/src/common/tagparser.cpp +++ b/src/common/tagparser.cpp @@ -8,7 +8,7 @@ * * $Id$ * - * XML tag parser. Functions for the start tags + helper functions + * XML tag parser * * Written by Moritz Bunkus . */ @@ -22,7 +22,6 @@ #include #include -#include "chapters.h" #include "common.h" #include "commonebml.h" #include "error.h" @@ -90,70 +89,3 @@ parse_xml_tags(const char *name, delete in; } - -void -fix_mandatory_tag_elements(EbmlElement *e) { - if (dynamic_cast(e) != NULL) { - KaxTagSimple &s = *static_cast(e); - GetChild(s); - GetChild(s); - - } else if (dynamic_cast(e) != NULL) { - KaxTagTargets &t = *static_cast(e); - GetChild(t); - - } - - if (dynamic_cast(e) != NULL) { - EbmlMaster *m; - int i; - - m = static_cast(e); - for (i = 0; i < m->ListSize(); i++) - fix_mandatory_tag_elements((*m)[i]); - } -} - -KaxTags * -select_tags_for_chapters(KaxTags &tags, - KaxChapters &chapters) { - KaxTags *new_tags; - KaxTagTargets *targets; - KaxTagEditionUID *t_euid; - KaxTagChapterUID *t_cuid; - int tags_idx, targets_idx; - bool copy; - - new_tags = NULL; - for (tags_idx = 0; tags_idx < tags.ListSize(); tags_idx++) { - if (dynamic_cast(tags[tags_idx]) == NULL) - continue; - copy = true; - targets = FINDFIRST(static_cast(tags[tags_idx]), - KaxTagTargets); - if (targets != NULL) { - for (targets_idx = 0; targets_idx < targets->ListSize(); targets_idx++) { - t_euid = dynamic_cast((*targets)[targets_idx]); - if ((t_euid != NULL) && - (find_edition_with_uid(chapters, uint64(*t_euid)) == NULL)) { - copy = false; - break; - } - t_cuid = dynamic_cast((*targets)[targets_idx]); - if ((t_cuid != NULL) && - (find_chapter_with_uid(chapters, uint64(*t_cuid)) == NULL)) { - copy = false; - break; - } - } - } - - if (copy) { - if (new_tags == NULL) - new_tags = new KaxTags; - new_tags->PushElement(*(tags[tags_idx]->Clone())); - } - } - - return new_tags; -} diff --git a/src/common/tagparser.h b/src/common/tagparser.h index 226c92484..25761411a 100644 --- a/src/common/tagparser.h +++ b/src/common/tagparser.h @@ -18,21 +18,10 @@ namespace libmatroska { class KaxTags; - class KaxChapters; }; -namespace libebml { - class EbmlElement; -}; - -using namespace libebml; using namespace libmatroska; void MTX_DLL_API parse_xml_tags(const char *name, KaxTags *tags); -void MTX_DLL_API fix_mandatory_tag_elements(EbmlElement *e); - -KaxTags *MTX_DLL_API select_tags_for_chapters(KaxTags &tags, - KaxChapters &chapters); - #endif // __TAGPARSER_H diff --git a/src/extract/cuesheets.cpp b/src/extract/cuesheets.cpp index 2c857f92a..e82ba4397 100644 --- a/src/extract/cuesheets.cpp +++ b/src/extract/cuesheets.cpp @@ -55,79 +55,11 @@ extern "C" { #include "mkvextract.h" #include "mm_io.h" #include "quickparser.h" +#include "tag_common.h" using namespace libmatroska; using namespace std; -static string -get_simple_tag(const char *name, - EbmlMaster &m) { - int i; - UTFstring uname; - string rvalue; - - uname = cstrutf8_to_UTFstring(name); - - for (i = 0; i < m.ListSize(); i++) - if (EbmlId(*m[i]) == KaxTagSimple::ClassInfos.GlobalId) { - KaxTagName *tname; - UTFstring utname; - - tname = FINDFIRST(m[i], KaxTagName); - if (tname == NULL) - continue; - utname = UTFstring(*static_cast(tname)); - if (utname == uname) { - KaxTagString *tvalue; - tvalue = FINDFIRST(m[i], KaxTagString); - if (tvalue != NULL) - return - UTFstring_to_cstrutf8(UTFstring(*static_cast - (tvalue))); - else - return ""; - } - } - - for (i = 0; i < m.ListSize(); i++) - if ((EbmlId(*m[i]) == KaxTag::ClassInfos.GlobalId) || - (EbmlId(*m[i]) == KaxTagSimple::ClassInfos.GlobalId)) { - rvalue = get_simple_tag(name, *static_cast(m[i])); - if (rvalue != "") - return rvalue; - } - - return ""; -} - -static int64_t -get_tag_tuid(KaxTag &tag) { - KaxTagTargets *targets; - KaxTagTrackUID *tuid; - - targets = FINDFIRST(&tag, KaxTagTargets); - if (targets == NULL) - return -1; - tuid = FINDFIRST(targets, KaxTagTrackUID); - if (tuid == NULL) - return -1; - return uint64(*static_cast(tuid)); -} - -static int64_t -get_tag_cuid(KaxTag &tag) { - KaxTagTargets *targets; - KaxTagChapterUID *cuid; - - targets = FINDFIRST(&tag, KaxTagTargets); - if (targets == NULL) - return -1; - cuid = FINDFIRST(targets, KaxTagChapterUID); - if (cuid == NULL) - return -1; - return uint64(*static_cast(cuid)); -} - static KaxTag * find_tag_for_track(int idx, int64_t tuid, @@ -148,8 +80,8 @@ find_tag_for_track(int idx, continue; tag_tuid = get_tag_tuid(*static_cast(m[i])); if (((tuid == -1) || (tag_tuid == -1) || (tuid == tag_tuid)) && - ((get_simple_tag("PART_NUMBER", - *static_cast(m[i])) == sidx) || + ((get_simple_tag_value("PART_NUMBER", + *static_cast(m[i])) == sidx) || (idx == -1))) return static_cast(m[i]); } @@ -167,7 +99,7 @@ get_global_tag(const char *name, if (tag == NULL) return ""; - return get_simple_tag(name, *tag); + return get_simple_tag_value(name, *tag); } static int64_t @@ -185,28 +117,6 @@ get_chapter_index(int idx, return -1; } -static string -get_simple_tag_name(KaxTagSimple &tag) { - KaxTagName *tname; - - tname = FINDFIRST(&tag, KaxTagName); - if (tname == NULL) - return ""; - return UTFstring_to_cstrutf8(UTFstring(*static_cast - (tname))); -} - -static string -get_simple_tag_value(KaxTagSimple &tag) { - KaxTagString *tstring; - - tstring = FINDFIRST(&tag, KaxTagString); - if (tstring == NULL) - return ""; - return UTFstring_to_cstrutf8(UTFstring(*static_cast - (tstring))); -} - #define print_if_global(name, format) \ _print_if_global(out, name, format, chapters.ListSize(), tuid, tags) static void @@ -234,7 +144,7 @@ _print_if_available(mm_io_c &out, KaxTag &tag) { string value; - value = get_simple_tag(name, tag); + value = get_simple_tag_value(name, tag); if ((value != "") && (value != get_global_tag(name, tuid, tags))) out.printf(format, value.c_str()); diff --git a/src/mkvmerge.cpp b/src/mkvmerge.cpp index e63dcee22..e0e02674e 100644 --- a/src/mkvmerge.cpp +++ b/src/mkvmerge.cpp @@ -88,6 +88,7 @@ #include "r_vobsub.h" #include "r_wav.h" #include "tagparser.h" +#include "tag_common.h" #include "xml_element_mapping.h" using namespace libmatroska; @@ -685,45 +686,6 @@ parse_and_add_tags(const char *file_name) { delete tags; } -/** \brief Convert older tags to current specs - */ -void -convert_old_tags(KaxTag *tag) { - KaxTagTargets *targets; - KaxTagSimple *simple; - KaxTagName *kname; - KaxTagString *kvalue; - string name, value; - int i; - - targets = &GetChild(*tag); - i = 0; - while (i < tag->ListSize()) { - simple = dynamic_cast((*tag)[i]); - if (simple == NULL) { - i++; - continue; - } - kname = FINDFIRST(simple, KaxTagName); - kvalue = FINDFIRST(simple, KaxTagString); - if ((kname != NULL) && (kvalue != NULL)) { - name = UTFstring_to_cstrutf8((const UTFstring &)(*kname)); - value = UTFstring_to_cstrutf8((const UTFstring &)(*kvalue)); - if (name == "CATALOG") - *static_cast(kname) = - cstrutf8_to_UTFstring("CATALOG_NUMBER"); - - else if (name == "DATE") - *static_cast(kname) = - cstrutf8_to_UTFstring("DATE_RELEASED"); - - else if (name == "LEVEL_TYPE") { - // TO BE DONE! - } - } - } -} - /** \brief Add some tags to the list of all tags */ void @@ -731,7 +693,6 @@ add_tags(KaxTag *tags) { if (!accept_tags) return; - convert_old_tags(tags); if (tags->ListSize() == 0) return; diff --git a/src/pr_generic.cpp b/src/pr_generic.cpp index ce5046f22..2d1fd431c 100644 --- a/src/pr_generic.cpp +++ b/src/pr_generic.cpp @@ -29,6 +29,7 @@ #include "mkvmerge.h" #include "pr_generic.h" #include "tagparser.h" +#include "tag_common.h" using namespace std; @@ -268,6 +269,7 @@ generic_packetizer_c::set_tag_track_uid() { if (ti->tags == NULL) return; + convert_old_tags(*ti->tags); for (is = 0; is < ti->tags->ListSize(); is++) { tag = (KaxTag *)(*ti->tags)[is];