[matroska] r927 - trunk/foo_matroska

[email protected]
Newsgroups gmane.comp.multimedia.matroska.cvs
Message-ID <[email protected]>
Author: toff
Date: 2004-10-27 00:55:05 +0400 (Wed, 27 Oct 2004)
New Revision: 927

Modified:
   trunk/foo_matroska/foo_input_matroska.cpp
   trunk/foo_matroska/matroska_parser.cpp
   trunk/foo_matroska/matroska_parser.h
Log:
Works only with tag having TargetTypeValue for now (mkvmerge 0.9.7)

Modified: trunk/foo_matroska/foo_input_matroska.cpp
===================================================================
--- trunk/foo_matroska/foo_input_matroska.cpp	2004-10-26 20:53:01 UTC (rev 926)
+++ trunk/foo_matroska/foo_input_matroska.cpp	2004-10-26 20:55:05 UTC (rev 927)
@@ -158,6 +158,7 @@
 
 		info->info_set_int("channels", m_expected_channels);
 		info->info_set_int("samplerate", m_expected_sample_rate);
+//		info->info_set_int("bitspersample", currentTrack.bitsPerSample);
 
 		{
 			packet_decoder::matroska_setup setup;

Modified: trunk/foo_matroska/matroska_parser.cpp
===================================================================
--- trunk/foo_matroska/matroska_parser.cpp	2004-10-26 20:53:01 UTC (rev 926)
+++ trunk/foo_matroska/matroska_parser.cpp	2004-10-26 20:55:05 UTC (rev 927)
@@ -25,20 +25,33 @@
 #include <string>
 using std::string;
 
-using namespace LIBEBML_NAMESPACE;
+using namespace LIBEBML_NAMESPACE;	
 using namespace LIBMATROSKA_NAMESPACE;
 
 static const char * rg_fields[]=
 {
-	"REPLAYGAIN_TRACK_GAIN","REPLAYGAIN_TRACK_PEAK","REPLAYGAIN_ALBUM_GAIN","REPLAYGAIN_ALBUM_PEAK"
+	"REPLAYGAIN_GAIN",
+	"REPLAYGAIN_PEAK"
 };
 
+static const char * rg_track_fields[]=
+{
+	"REPLAYGAIN_TRACK_GAIN",
+	"REPLAYGAIN_TRACK_PEAK"
+};
+
+static const char * rg_album_fields[]=
+{
+	"REPLAYGAIN_ALBUM_GAIN",
+	"REPLAYGAIN_ALBUM_PEAK"
+};
+
 #define MATROSKA_TAG_IDX 0
 #define FOOBAR2K_TAG_IDX 1
 
 static const char * chapter_tag_mapping[][2] =
-{
-	{ "SET_PART", "TRACKNUMBER"	}
+{	
+	{ "PART_NUMBER", "TRACKNUMBER" }
 };
 
 static const char * edition_tag_mapping[][2] =
@@ -49,22 +62,19 @@
 
 static const char * hidden_edition_field[] =
 {
-	"CATALOG",
-	"TOTAL_MEDIA_PARTS",
-	"TOTAL_SET_PARTS"
+	"CATALOG_NUMBER",
+	"TOTAL_PARTS"
 };
 
 static const char * hidden_chapter_field[] =
 {
 	"CD_TRACK_FLAGS",
-	"TOTAL_SET_PARTS"
 };
 
 bool starts_with(const string &s, const char *start) {
   return strncmp(s.c_str(), start, strlen(start)) == 0;
 }
 
-
 uint64 MatroskaAudioParser::SecondsToTimecode(double seconds)
 {
 	return (uint64)floor(seconds * 1000000000);
@@ -92,7 +102,10 @@
 {
 	name = L"";
 	value = L"";
+	language = "und";
+	defaultFlag = 1;
 	hidden = false;
+	removalPending = false;
 };
 
 MatroskaTagInfo::MatroskaTagInfo()
@@ -101,39 +114,55 @@
 	targetEditionUID = 0;
 	targetChapterUID = 0;
 	targetAttachmentUID = 0;
+	targetTypeValue = 0;
 };
 
-void MatroskaTagInfo::SetTagValue(const char *name, const char *value)
+void MatroskaTagInfo::SetTagValue(const char *name, const char *value, int index)
 {
-	for (size_t s = 0; s < tags.size(); s++) {
+	for (size_t s = 0; s < tags.size(); s++)
+	{
 		MatroskaSimpleTag &currentSimpleTag = tags.at(s);
-		if ((!strcmpi(currentSimpleTag.name.GetUTF8().c_str(), name))
-			&& (!strcmpi(currentSimpleTag.value.GetUTF8().c_str(), value)))
+		if (strcmpi(currentSimpleTag.name.GetUTF8().c_str(), name) == 0)			
 		{
-			currentSimpleTag.value.SetUTF8(value);
-			return;
+			if(index == 0)
+			{
+				currentSimpleTag.value.SetUTF8(value);
+				currentSimpleTag.removalPending = false;
+				return;
+			}
+			index--;
 		}
 	}
 
 	// If we are here then we didn't find this tag in the vector already
 	MatroskaSimpleTag newSimpleTag;
 	newSimpleTag.name.SetUTF8(name);
-	newSimpleTag.value.SetUTF8(value);
+	newSimpleTag.value.SetUTF8(value);	
+	newSimpleTag.removalPending = false;
 	tags.push_back(newSimpleTag);
 };
 
-void MatroskaTagInfo::ClearTagsButNotHiddenOne()
+void MatroskaTagInfo::RemoveMarkedTags()
 {
 	for (int i = tags.size()-1; i >= 0; i--)
 	{
 		MatroskaSimpleTag &simpleTag = tags.at(i);
-		if(simpleTag.hidden == false)
+		if(simpleTag.removalPending == true)
 		{
 			tags.erase(tags.begin() + i);
 		}
 	}
 }
 
+void MatroskaTagInfo::MarkAllAsRemovalPending()
+{
+	for (int i = tags.size()-1; i >= 0; i--)
+	{
+		MatroskaSimpleTag &simpleTag = tags.at(i);
+		simpleTag.removalPending = true;
+	}
+}
+
 MatroskaChapterDisplayInfo::MatroskaChapterDisplayInfo()  {
 	string = L"";
 };
@@ -633,6 +662,15 @@
 			KaxTagAttachmentUID & MyKaxTagAttachmentUID = GetChild<KaxTagAttachmentUID>(MyKaxTagTargets);
 			*static_cast<EbmlUInteger *>(&MyKaxTagAttachmentUID) = currentTag.targetAttachmentUID;
 		}
+		if(currentTag.targetTypeValue != 0) {
+			KaxTagTargetTypeValue& MyKaxTagTargetTypeValue = GetChild<KaxTagTargetTypeValue>(MyKaxTagTargets);
+			*static_cast<EbmlUInteger *>(&MyKaxTagTargetTypeValue) = currentTag.targetTypeValue;
+			if(!currentTag.targetType.empty())
+			{
+				KaxTagTargetType& MyKaxTagTargetType = GetChild<KaxTagTargetType>(MyKaxTagTargets);
+				*static_cast<EbmlString *>(&MyKaxTagTargetType) = currentTag.targetType;				
+			}
+		}
 		
 		// Add the millions of simple tags we can have ;)
 		KaxTagSimple *MySimpleTag_last = NULL;
@@ -653,6 +691,12 @@
 
 			KaxTagString & MyKaxTagString = GetChild<KaxTagString>(*MySimpleTag);
 			*static_cast<EbmlUnicodeString *>(&MyKaxTagString) = currentSimpleTag.value;
+			
+			KaxTagLangue& MyKaxTagLangue = GetChild<KaxTagLangue>(*MySimpleTag);
+			*static_cast<EbmlString *>(&MyKaxTagLangue) = currentSimpleTag.language;
+
+			KaxTagDefault& MyKaxTagDefault = GetChild<KaxTagDefault>(*MySimpleTag);
+			*static_cast<EbmlUInteger *>(&MyKaxTagDefault) = currentSimpleTag.defaultFlag;			
 		}
 
 		m_IOCallback.setFilePointer(m_TagPos);
@@ -704,40 +748,6 @@
 	return 0;
 };
 
-/*
-void MatroskaAudioParser::AddTags(const file_info *info)
-{
-	// We use the subsong index to find out which track+chapter these tags apply to
-	int subsong = info->get_subsong_index();
-	if (m_Chapters.size() > 0) {
-		// Ok we add the tags to tags with chapter+track UID's
-	} else {
-		// Just add the tags to the track UID
-		MatroskaTagInfo *trackTag = FindTagWithTrackUID(m_Tracks.at(m_CurrentTrackNo).trackUID);
-		if (trackTag == NULL) {
-			MatroskaTagInfo tempTag;
-			tempTag.targetTrackUID = m_Tracks.at(m_CurrentTrackNo).trackUID;
-			m_Tags.push_back(tempTag);
-			trackTag = &m_Tags.at(m_Tags.size()-1);
-		}
-		int metaDataCount = info->meta_get_count();
-		int m;
-		for (m = 0; m < metaDataCount; m++) {
-			const char *name = info->meta_enum_name(m);
-			const char *value = info->meta_enum_value(m);
-			if ((name != NULL) && (value != NULL)) {
-				trackTag->SetTagValue(name, value);
-			}
-		}
-		for (m = 0; m < tabsize(rg_fields); m++)
-		{
-			const char * value = info->info_get(rg_fields[m]);
-			if (value) trackTag->SetTagValue(rg_fields[m],value);
-		}
-	}
-};
-*/
-
 static const char* foobar2k_to_matroska_edition_tag(const char * name)
 {
 	if (!stricmp_utf8(name, "ALBUM"))
@@ -764,100 +774,146 @@
 		return name;
 }
 
+int meta_get_num(const file_info *info, const char* name, int idx)
+{
+	assert(is_valid_utf8(name));
+	int n, m = min(info->meta_get_count(), idx);
+	int rv = 0;
+	for(n=0; n<m; n++)
+	{
+		if (!stricmp_utf8(name, info->meta_enum_name(n)))
+			rv++;
+	}
+	return rv;
+}
+
 void MatroskaAudioParser::SetTags(const file_info *info)
 {
-	MarkHiddenTags();
+	int i, idx;
+	const char *name, *value;	
 
-	// If there only a track, set all its tags.
-	if ((m_Editions.size() < 1) && (m_CurrentEdition == NULL)) {
-		// Now, add the tags to the Track UID
-		MatroskaTagInfo *trackTag = FindTagWithTrackUID(m_Tracks.at(m_CurrentTrackNo).trackUID);
+	if (m_Chapters.size() == 0)
+	{		
+		// No chapters, works on track
+		MatroskaTagInfo *trackTag;
+		trackTag = FindTagWithTrackUID(m_Tracks.at(m_CurrentTrackNo).trackUID);
 		if (trackTag == NULL) {
+			// The tag doesn't exist yet
 			MatroskaTagInfo tempTag;
 			tempTag.targetTrackUID = m_Tracks.at(m_CurrentTrackNo).trackUID;
 			m_Tags.push_back(tempTag);
 			trackTag = &m_Tags.at(m_Tags.size()-1);
 		}
-		// Clear the existing tags
-		trackTag->ClearTagsButNotHiddenOne();
+		if(trackTag->targetTypeValue == 0)
+			trackTag->targetTypeValue = 50;
+		trackTag->MarkAllAsRemovalPending();
 		int metaDataCount = info->meta_get_count();
-		int m;
-		for (m = 0; m < metaDataCount; m++) {
-			const char *name = foobar2k_to_matroska_chapter_tag(info->meta_enum_name(m));
-			const char *value = info->meta_enum_value(m);
+		for (i = 0; i < metaDataCount; i++)
+		{
+			name = info->meta_enum_name(i);
+			value = info->meta_enum_value(i);
+			idx = meta_get_num(info, name, i);
+			name = foobar2k_to_matroska_chapter_tag(name);
 			if ((name != NULL) && (value != NULL)) {
-				trackTag->SetTagValue(name, value);
+				trackTag->SetTagValue(name, value, idx);
 			}
 		}
 		// Add the replay_gain tags
-		for (m = 0; m < tabsize(rg_fields); m++)
+		value = info->info_get("REPLAYGAIN_TRACK_GAIN");
+		if (value)
+			trackTag->SetTagValue("REPLAYGAIN_GAIN", value);
+		value = info->info_get("REPLAYGAIN_TRACK_PEAK");
+		if (value)
+			trackTag->SetTagValue("REPLAYGAIN_PEAK", value);
+		trackTag->RemoveMarkedTags();
+	}
+	
+	// Set global track tags as album tags
+	if ((m_Chapters.size() > 0) && (m_CurrentChapter != NULL))
+	{
+		MatroskaTagInfo *trackTag;
+		trackTag = FindTagWithTrackUID(m_Tracks.at(m_CurrentTrackNo).trackUID);
+		if (trackTag == NULL)
 		{
-			//trackTag->targetTrackUID = m_Tracks.at(m_CurrentTrackNo).trackUID;
-			const char * value = info->info_get(rg_fields[m]);
-			if (value) trackTag->SetTagValue(rg_fields[m],value);
-		}
-	}
-
-	//If there's not only a track, set all the Edition tags
-	if ((m_Editions.size() > 0) && (m_CurrentEdition != NULL)) {
-	// Ok we add the tags to tag with edition+track UID's
-		MatroskaTagInfo *editionTag = FindTagWithEditionUID(m_CurrentEdition->editionUID, m_Tracks.at(m_CurrentTrackNo).trackUID);
-		if (editionTag == NULL) {
 			MatroskaTagInfo tempTag;
-			tempTag.targetTrackUID = m_Tracks.at(m_CurrentTrackNo).trackUID;
-			tempTag.targetEditionUID = m_CurrentEdition->editionUID;
+			tempTag.targetTrackUID = m_Tracks.at(m_CurrentTrackNo).trackUID;			
 			m_Tags.push_back(tempTag);
-			editionTag = &m_Tags.at(m_Tags.size()-1);
+			trackTag = &m_Tags.at(m_Tags.size()-1);
 		}
-		// Clear the existing tags
-		editionTag->ClearTagsButNotHiddenOne();
+		if(trackTag->targetTypeValue == 0)
+			trackTag->targetTypeValue = 50;
+		trackTag->MarkAllAsRemovalPending();
 		int metaDataCount = info->meta_get_count();
-		int m;
-		for (m = 0; m < metaDataCount; m++) {
-			const char *name = info->meta_enum_name(m);
-			const char *value = info->meta_enum_value(m);
-			if (starts_with(name, "ALBUM") || starts_with(name, "SUBALBUM") || starts_with(name, "DISCID")) {
-				name = foobar2k_to_matroska_edition_tag(info->meta_enum_name(m));
-			} else name = NULL;
+		for (i = 0; i < metaDataCount; i++)
+		{
+			name = info->meta_enum_name(i);
+			value = info->meta_enum_value(i);
+			idx = meta_get_num(info, name, i);
+			if (starts_with(name, "ALBUM") ||
+				starts_with(name, "SUBALBUM") ||
+				starts_with(name, "DISCID"))
+			{
+				name = foobar2k_to_matroska_edition_tag(name);
+			} else {
+				name = NULL;
+			}
 			if ((name != NULL) && (value != NULL)) {
-				editionTag->SetTagValue(name, value);
+				trackTag->SetTagValue(name, value, idx);
 			}
 		}
+		value = info->info_get("REPLAYGAIN_ALBUM_GAIN");
+		if (value)
+			trackTag->SetTagValue("REPLAYGAIN_GAIN", value);
+		value = info->info_get("REPLAYGAIN_ALBUM_PEAK");
+		if (value)
+			trackTag->SetTagValue("REPLAYGAIN_PEAK", value);
+		trackTag->RemoveMarkedTags();
 	}
 
+
 	//If there's not only a track, set all the chapter tags
-	if ((m_Chapters.size() > 0) && (m_CurrentChapter != NULL)) {
+	if ((m_Chapters.size() > 0) && (m_CurrentChapter != NULL))
+	{
 		// Ok we add the tags to tag with chapter+track UID's
-		MatroskaTagInfo *chapterTag = FindTagWithChapterUID(m_CurrentChapter->chapterUID, m_Tracks.at(m_CurrentTrackNo).trackUID);
-		if (chapterTag == NULL) {
+		MatroskaTagInfo *chapterTag;		
+		chapterTag = FindTagWithChapterUID(m_CurrentChapter->chapterUID,
+			m_Tracks.at(m_CurrentTrackNo).trackUID);
+		if (chapterTag == NULL)
+		{
 			MatroskaTagInfo tempTag;
 			tempTag.targetTrackUID = m_Tracks.at(m_CurrentTrackNo).trackUID;
 			tempTag.targetChapterUID = m_CurrentChapter->chapterUID;
 			m_Tags.push_back(tempTag);
 			chapterTag = &m_Tags.at(m_Tags.size()-1);
 		}
-		// Clear the existing tags but not hidden ones
-		chapterTag->ClearTagsButNotHiddenOne();
+		if(chapterTag->targetTypeValue == 0)
+			chapterTag->targetTypeValue = 30;
+		chapterTag->MarkAllAsRemovalPending();
 		int metaDataCount = info->meta_get_count();
-		int m;
-		for (m = 0; m < metaDataCount; m++) {			
-			const char *name = info->meta_enum_name(m);
-			const char *value = info->meta_enum_value(m);
-			if (starts_with(name, "ALBUM") || starts_with(name, "SUBALBUM") || starts_with(name, "DISCID"))
+		for (i = 0; i < metaDataCount; i++)
+		{
+			name = info->meta_enum_name(i);
+			value = info->meta_enum_value(i);
+			idx = meta_get_num(info, name, i);
+			if (starts_with(name, "ALBUM") ||
+				starts_with(name, "SUBALBUM") ||
+				starts_with(name, "DISCID"))
+			{
 				name = NULL;
-			else {
-				name = foobar2k_to_matroska_chapter_tag(info->meta_enum_name(m));
+			} else {
+				name = foobar2k_to_matroska_chapter_tag(name);
 			}
 			if ((name != NULL) && (value != NULL)) {
-				chapterTag->SetTagValue(name, value);
+				chapterTag->SetTagValue(name, value, idx);
 			}
 		}
-		for (m = 0; m < tabsize(rg_fields); m++)
-		{
-			//chapterTag->targetChapterUID = m_CurrentChapter->chapterUID;
-			const char * value = info->info_get(rg_fields[m]);
-			if (value) chapterTag->SetTagValue(rg_fields[m],value);
-		}
+		value = info->info_get("REPLAYGAIN_TRACK_GAIN");
+		if (value)
+			chapterTag->SetTagValue("REPLAYGAIN_GAIN", value);
+		value = info->info_get("REPLAYGAIN_TRACK_PEAK");
+		if (value)
+			chapterTag->SetTagValue("REPLAYGAIN_PEAK", value);
+		chapterTag->RemoveMarkedTags();
 	}
 };
 
@@ -1114,151 +1170,165 @@
 	return AtLeastOneChapter;
 }
 
-// Manage and translate tags according to this:
-// http://www.pepper-prod.com/tags.html
-
-bool MatroskaAudioParser::SetFB2KInfo(file_info *info)
+void MatroskaAudioParser::SetAlbumTags(file_info *info,
+									   MatroskaTagInfo* AlbumTags,
+									   MatroskaTagInfo* TrackTags)
 {
-	if (m_MuxingApp.length() > 0)
-		info->info_set("MUXING_APP", m_MuxingApp.GetUTF8().c_str());
-	if (m_WritingApp.length() > 0)
-		info->info_set("WRITING_APP", m_WritingApp.GetUTF8().c_str());
-	if (m_FileTitle.length() > 0)
-		info->info_set("TITLE", m_FileTitle.GetUTF8().c_str());
+	if (AlbumTags == NULL)
+		return;
 
-	MatroskaTagInfo *TrackTags = FindTagWithTrackUID(m_Tracks.at(m_CurrentTrackNo).trackUID);
-
-	// Parse the current Track tags if any.
-	if((m_Editions.size() < 1) && (TrackTags != NULL))
-	{		
-		for (size_t s = 0; s < TrackTags->tags.size(); s++)
+	for (size_t s = 0; s < AlbumTags->tags.size(); s++)
+	{
+		MatroskaSimpleTag &simpleTag = AlbumTags->tags.at(s);
+		
+		if (is_rg_field(simpleTag.name.GetUTF8().c_str()))
 		{
-			const MatroskaSimpleTag &simpleTag = TrackTags->tags.at(s);
-			
-			if (is_rg_field(simpleTag.name.GetUTF8().c_str()))
+			if(IsTagNamed(simpleTag, "REPLAYGAIN_GAIN"))
 			{
-				info->info_set(simpleTag.name.GetUTF8().c_str(),
+				info->info_set("REPLAYGAIN_ALBUM_GAIN",
 					simpleTag.value.GetUTF8().c_str());	
+			} else if(IsTagNamed(simpleTag, "REPLAYGAIN_PEAK")) {
+				info->info_set("REPLAYGAIN_ALBUM_PEAK",
+					simpleTag.value.GetUTF8().c_str());	
 			}
-			else {
-				info->meta_add(
-					matroska_to_foobar2k_chapter_tag(simpleTag.name.GetUTF8().c_str()),
-					simpleTag.value.GetUTF8().c_str());
-			}
 		}
-	}
-
-	MatroskaTagInfo *EditionTags = NULL;
-	if(m_CurrentEdition != NULL)
-	{
-		EditionTags = FindTagWithEditionUID(m_CurrentEdition->editionUID,
-			m_Tracks.at(m_CurrentTrackNo).trackUID);
-	}
-	MatroskaTagInfo *ChapterTags = NULL;
-	if(m_CurrentChapter != NULL)
-	{
-		ChapterTags = FindTagWithChapterUID(m_CurrentChapter->chapterUID,
-			m_Tracks.at(m_CurrentTrackNo).trackUID);		
-	}	
-
-	// Parse the current Edition tags if any.
-	if (EditionTags != NULL)
-	{
-		for (size_t s = 0; s < EditionTags->tags.size(); s++)
+		else if (is_hidden_edition_field(simpleTag.name.GetUTF8().c_str()))
 		{
-			const MatroskaSimpleTag &simpleTag = EditionTags->tags.at(s);
-			
-			if (is_rg_field(simpleTag.name.GetUTF8().c_str()))
+			// Ignored tag, will be rewrited later
+			simpleTag.hidden = true;
+		}
+		else if(IsTagNamed(simpleTag,"TITLE"))
+		{
+			// Special case for Edition/TITLE
+			if(TagExistsAtChapterLevel(TrackTags, "ALBUM"))
 			{
-				info->info_set(simpleTag.name.GetUTF8().c_str(),
-					simpleTag.value.GetUTF8().c_str());	
+				info->meta_add("ALBUM TITLE", simpleTag.value.GetUTF8().c_str());
+			} else {
+				info->meta_add("ALBUM", simpleTag.value.GetUTF8().c_str());
 			}
-			else if (is_hidden_edition_field(simpleTag.name.GetUTF8().c_str()))
+		}
+		else if(IsTagNamed(simpleTag,"SUBTITLE"))
+		{
+			// Special case for Edition/SUBTITLE
+			if(TagExistsAtChapterLevel(TrackTags, "SUBALBUM"))
 			{
-				// Ignore tag
+				info->meta_add("ALBUM SUBTITLE", simpleTag.value.GetUTF8().c_str());
+			} else {
+				info->meta_add("SUBALBUM", simpleTag.value.GetUTF8().c_str());
 			}
-			else if(IsTagNamed(simpleTag,"TITLE"))
-			{
-				// Special case for Edition/TITLE
-				if(TagExistsAtChapterLevel(ChapterTags, "ALBUM"))
-				{
-					info->meta_add("ALBUM TITLE", simpleTag.value.GetUTF8().c_str());
-				} else {
-					info->meta_add("ALBUM", simpleTag.value.GetUTF8().c_str());
-				}
-			}
-			else if(IsTagNamed(simpleTag,"SUBTITLE"))
-			{
-				// Special case for Edition/SUBTITLE
-				if(TagExistsAtChapterLevel(ChapterTags, "SUBALBUM"))
-				{
-					info->meta_add("ALBUM SUBTITLE", simpleTag.value.GetUTF8().c_str());
-				} else {
-					info->meta_add("SUBALBUM", simpleTag.value.GetUTF8().c_str());
-				}
-			}
-			else if(IsTagNamed(simpleTag,"DISCID"))
-			{
-				info->meta_add("DISCID", simpleTag.value.GetUTF8().c_str());
-			}
-			else if(IsTagNamed(simpleTag,"COMMENTS"))
-			{
-				info->meta_add("ALBUM COMMENT", simpleTag.value.GetUTF8().c_str());
-			}
-			else if((!AreTagsIdenticalAtAllLevels(simpleTag.name.GetUTF8().c_str()))
-					|| (!TagExistsAtChapterLevel(ChapterTags, simpleTag.name.GetUTF8().c_str())))
-			{
-				// Prefix tag with "ALBUM "
-				char newTagName[255] = "ALBUM ";
-				strncat(newTagName, matroska_to_foobar2k_edition_tag(simpleTag.name.GetUTF8().c_str()),255);
-				info->meta_add(newTagName, simpleTag.value.GetUTF8().c_str());					
-			}
-			else 
-			{
-				// Ignore tag
-			}
 		}
+		else if(IsTagNamed(simpleTag,"DISCID"))
+		{
+			info->meta_add("DISCID", simpleTag.value.GetUTF8().c_str());
+		}
+		else if(IsTagNamed(simpleTag,"COMMENTS"))
+		{
+			info->meta_add("ALBUM COMMENT", simpleTag.value.GetUTF8().c_str());
+		}
+		else if((!AreTagsIdenticalAtAllLevels(simpleTag.name.GetUTF8().c_str()))
+			|| (!TagExistsAtChapterLevel(TrackTags, simpleTag.name.GetUTF8().c_str())))
+		{
+			// Prefix tag with "ALBUM "
+			char newTagName[255] = "ALBUM ";
+			strncat(newTagName, matroska_to_foobar2k_edition_tag(simpleTag.name.GetUTF8().c_str()),255);
+			info->meta_add(newTagName, simpleTag.value.GetUTF8().c_str());					
+		}
+		else 
+		{
+			// Ignored tag, will be rewrited later
+			simpleTag.hidden = true;
+		}
 	}
+}
 
-	// Parse the current Chapter tags if any.
-	if(ChapterTags != NULL)
+void MatroskaAudioParser::SetTrackTags(file_info *info, MatroskaTagInfo* TrackTags)
+{
+	if(TrackTags == NULL)
+		return;
+
+	for (size_t s = 0; s < TrackTags->tags.size(); s++)
 	{
-		for (size_t s = 0; s < ChapterTags->tags.size(); s++)
+		MatroskaSimpleTag &simpleTag = TrackTags->tags.at(s);
+		
+		if (is_rg_field(simpleTag.name.GetUTF8().c_str()))
 		{
-			const MatroskaSimpleTag &simpleTag = ChapterTags->tags.at(s);
-			
-			if (is_rg_field(simpleTag.name.GetUTF8().c_str()))
+			if(IsTagNamed(simpleTag, "REPLAYGAIN_GAIN"))
 			{
-				info->info_set(simpleTag.name.GetUTF8().c_str(),
+				info->info_set("REPLAYGAIN_TRACK_GAIN",
 					simpleTag.value.GetUTF8().c_str());	
+			} else if(IsTagNamed(simpleTag, "REPLAYGAIN_PEAK")) {
+				info->info_set("REPLAYGAIN_TRACK_PEAK",
+					simpleTag.value.GetUTF8().c_str());	
 			}
-			else if (is_hidden_chapter_field(simpleTag.name.GetUTF8().c_str()))
-			{
-				// Ignore tag
+		}
+		else if (is_hidden_chapter_field(simpleTag.name.GetUTF8().c_str()))
+		{
+			// Ignore tag
+			simpleTag.hidden = true;
+		}
+		else if(IsTagNamed(simpleTag,"COMMENTS"))
+		{
+			info->meta_add("COMMENT", simpleTag.value.GetUTF8().c_str());
+		}
+		else if(IsTagNamed(simpleTag,"ALBUM"))
+		{
+			if(!TagExistsAtEditionLevel(TrackTags, "TITLE") && AreTagsIdenticalAtChapterLevel("ALBUM")) {
+				info->meta_add("ALBUM", simpleTag.value.GetUTF8().c_str());
+			} else {
+				info->meta_add("ORIGINAL_ALBUM", simpleTag.value.GetUTF8().c_str());
 			}
-			else if(IsTagNamed(simpleTag,"COMMENTS"))
-			{
-				info->meta_add("COMMENT", simpleTag.value.GetUTF8().c_str());
-			}
-			else if(IsTagNamed(simpleTag,"ALBUM"))
-			{
-				if(!TagExistsAtEditionLevel(TrackTags, "TITLE") && AreTagsIdenticalAtChapterLevel("ALBUM")) {
-					info->meta_add("ALBUM", simpleTag.value.GetUTF8().c_str());
-				} else {
-					info->meta_add("ORIGINAL_ALBUM", simpleTag.value.GetUTF8().c_str());
-				}
-			}
-			else
-			{
-				info->meta_add(
-					matroska_to_foobar2k_chapter_tag(simpleTag.name.GetUTF8().c_str()),
-					simpleTag.value.GetUTF8().c_str());	
-			}
-		}		
+		}
+		else
+		{
+			info->meta_add(
+				matroska_to_foobar2k_chapter_tag(simpleTag.name.GetUTF8().c_str()),
+				simpleTag.value.GetUTF8().c_str());	
+		}
 	}
+}
 
+bool MatroskaAudioParser::SetFB2KInfo(file_info *info)
+{
+	if (m_MuxingApp.length() > 0)
+		info->info_set("MUXING_APP", m_MuxingApp.GetUTF8().c_str());
+	if (m_WritingApp.length() > 0)
+		info->info_set("WRITING_APP", m_WritingApp.GetUTF8().c_str());
+	if (m_FileTitle.length() > 0)
+		info->info_set("TITLE", m_FileTitle.GetUTF8().c_str());
+
+	MatroskaTagInfo *TrackTags = FindTagWithTrackUID(m_Tracks.at(m_CurrentTrackNo).trackUID);
+	MatroskaTagInfo *ChapterTags = NULL;
 	if(m_CurrentChapter != NULL)
 	{
+		ChapterTags = FindTagWithChapterUID(m_CurrentChapter->chapterUID,
+			m_Tracks.at(m_CurrentTrackNo).trackUID);		
+	}
+	/*
+	MatroskaTagInfo *EditionTags = NULL;
+	if(m_CurrentEdition != NULL)
+	{
+		EditionTags = FindTagWithEditionUID(m_CurrentEdition->editionUID,
+			m_Tracks.at(m_CurrentTrackNo).trackUID);
+	}
+	if(EditionTags != NULL && EditionTags->targetTypeValue == 50)
+	{
+		SetAlbumTags(info, EditionTags, ChapterTags);
+	}
+	*/
+	if(TrackTags != NULL)
+	{
+		if(TrackTags->targetTypeValue == 50)
+		{
+			SetAlbumTags(info, TrackTags, ChapterTags);
+			SetTrackTags(info, ChapterTags);
+		} else if (TrackTags->targetTypeValue == 30) {
+			SetTrackTags(info, TrackTags);
+		}
+	}
+	
+	// Last chance,
+	if(m_CurrentChapter != NULL)
+	{
 		// If TITLE tag is empty we get it from the chapter name
 		if ((info->meta_get("TITLE") == NULL) || (strlen(info->meta_get("TITLE")) == 0))
 			info->meta_set("TITLE", m_CurrentChapter->display.at(0).string.GetUTF8().c_str());
@@ -1275,84 +1345,17 @@
 		}			
 	}
 
-
 	return true;
 };
 
 void MatroskaAudioParser::MarkHiddenTags()
 {
-	// We do like in MatroskaAudioParser::SetFB2KInfo but instead of ignoring
-	// tag we copy them to keep track of them
-
-	if(m_CurrentChapter == NULL)
-		return;	 // Just a simple track with no chapters, no hidden tags
-
-	MatroskaTagInfo *TrackTags = FindTagWithTrackUID(m_Tracks.at(m_CurrentTrackNo).trackUID);
-
-	// We have chapters 
-
-	MatroskaTagInfo *EditionTags = NULL;
-	EditionTags = FindTagWithEditionUID(m_CurrentEdition->editionUID,
-			m_Tracks.at(m_CurrentTrackNo).trackUID);
-
-	MatroskaTagInfo *ChapterTags = NULL;
-	ChapterTags = FindTagWithChapterUID(m_CurrentChapter->chapterUID,
-			m_Tracks.at(m_CurrentTrackNo).trackUID);
-
-	if (EditionTags != NULL)
-	{
-		for (size_t s = 0; s < EditionTags->tags.size(); s++)
-		{
-			MatroskaSimpleTag &simpleTag = EditionTags->tags.at(s);
-			
-			if (is_rg_field(simpleTag.name.GetUTF8().c_str()))
-			{
-				// Do nothing
-			}
-			else if (is_hidden_edition_field(simpleTag.name.GetUTF8().c_str()))
-			{
-				// Ignored tags will need to be rewrited later
-				simpleTag.hidden = true;
-			}
-			else if(IsTagNamed(simpleTag,"TITLE"))
-			{
-				// Do nothing
-			}
-			else if(IsTagNamed(simpleTag,"SUBTITLE"))
-			{
-				// Do nothing
-			}
-			else if((!AreTagsIdenticalAtAllLevels(simpleTag.name.GetUTF8().c_str()))
-					|| (!TagExistsAtChapterLevel(ChapterTags, simpleTag.name.GetUTF8().c_str())))
-			{
-				// Do nothing
-			}
-			else 
-			{
-				// Ignored tags will need to be rewrited later
-				simpleTag.hidden = true;
-			}
-		}
-	}
-
-	if(ChapterTags != NULL)
-	{
-		for (size_t s = 0; s < ChapterTags->tags.size(); s++)
-		{
-			MatroskaSimpleTag &simpleTag = ChapterTags->tags.at(s);
-			
-			if (is_rg_field(simpleTag.name.GetUTF8().c_str()))
-			{
-				// Do nothing
-			}
-			else if (is_hidden_chapter_field(simpleTag.name.GetUTF8().c_str()))
-			{
-				simpleTag.hidden = true;
-			}
-		}
-	}
-
-	return;
+	// We call MatroskaAudioParser::SetFB2KInfo with a dummy file_info that
+	// do nothing, so we will only mark hidden tags.
+	// Hidden tag will be copied to keep track of them.
+	// This is needed cause tag are read and written in 2 different instances
+	dummy_file_info info;
+	SetFB2KInfo(&info);
 };
 
 void MatroskaAudioParser::SetCurrentTrack(uint32 newTrackNo)
@@ -1724,6 +1727,7 @@
 		if(IS_ELEMENT_ID(KaxTag))
 		{
 			MatroskaTagInfo newTag;
+			newTag.targetTypeValue = 50;
 			KaxTag *tagElement = (KaxTag*)Element;
 			NOTE("New Tag");
 			for (j = 0; j < tagElement->ListSize(); j++)
@@ -1755,6 +1759,16 @@
 							newTag.targetAttachmentUID = uint64(*static_cast<EbmlUInteger *>(Element));
 							NOTE1("- TargetAttachmentUID : %I64d", newTag.targetAttachmentUID);
 						}
+						else if(IS_ELEMENT_ID(KaxTagTargetTypeValue))
+						{
+							newTag.targetTypeValue = uint32(*static_cast<EbmlUInteger *>(Element));
+							NOTE1("- TargetTypeValue : %d", newTag.targetTypeValue);
+						}
+						else if(IS_ELEMENT_ID(KaxTagTargetType))
+						{
+							newTag.targetType = std::string(*static_cast<KaxTagTargetType *>(Element));
+							NOTE1("- TargetType : %s", newTag.targetType.c_str());
+						}
 					}
 				}
 				else if(IS_ELEMENT_ID(KaxTagSimple))
@@ -1775,6 +1789,16 @@
 							newSimpleTag.value = UTFstring(*static_cast <EbmlUnicodeString *>(Element)).c_str();
 							NOTE1("- Value : %s", newSimpleTag.value.GetUTF8().c_str());
 						}
+						else if(IS_ELEMENT_ID(KaxTagDefault))
+						{
+							newSimpleTag.defaultFlag = uint32(*static_cast<EbmlUInteger *>(Element));
+							NOTE1("- TargetTypeValue : %d", newSimpleTag.default);
+						}
+						else if(IS_ELEMENT_ID(KaxTagLangue))
+						{
+							newSimpleTag.language = std::string(*static_cast <KaxTagLangue *>(Element));
+							NOTE1("- Language : %s", newSimpleTag.language.c_str());
+						}
 						else if(IS_ELEMENT_ID(KaxTagSimple))
 						{
 							// ignore sub-tags

Modified: trunk/foo_matroska/matroska_parser.h
===================================================================
--- trunk/foo_matroska/matroska_parser.h	2004-10-26 20:53:01 UTC (rev 926)
+++ trunk/foo_matroska/matroska_parser.h	2004-10-26 20:55:05 UTC (rev 927)
@@ -113,19 +113,26 @@
 
 	UTFstring name;
 	UTFstring value;
+	uint32 defaultFlag;
+	std::string language;
+
 	bool hidden;
+	bool removalPending;
 };
 
 class MatroskaTagInfo {
 public:
 	MatroskaTagInfo();
-	void SetTagValue(const char *name, const char *value);
-	void ClearTagsButNotHiddenOne();
-		
+	void SetTagValue(const char *name, const char *value, int index = 0);
+	void MarkAllAsRemovalPending();
+	void RemoveMarkedTags();
+	
 	uint64 targetTrackUID;
 	uint64 targetEditionUID;
 	uint64 targetChapterUID;
 	uint64 targetAttachmentUID;
+	uint32 targetTypeValue;
+	std::string targetType;
 
 	std::vector<MatroskaSimpleTag> tags;
 };
@@ -282,6 +289,10 @@
 	bool AreTagsIdenticalAtChapterLevel(const char * name);
 	void MarkHiddenTags();
 
+	void SetAlbumTags(file_info *info, MatroskaTagInfo* AlbumTags, MatroskaTagInfo* TrackTags);
+	void SetTrackTags(file_info *info, MatroskaTagInfo* TrackTags);
+		
+
 	Foobar2000ReaderIOCallback m_IOCallback;
 	EbmlStream m_InputStream;
 	/// The main/base/master element, should be the segment
@@ -325,4 +336,37 @@
 
 void PrintChapters(std::vector<MatroskaChapterInfo> &theChapters);
 
+class dummy_playable_location : public playable_location
+{
+	const char * get_path() const { return NULL; }
+	void set_path(const char*) {}	
+	int get_number() const { return 0; }
+	void set_number(int) { };	
+};
+
+class dummy_file_info : public file_info
+{
+private:
+	dummy_playable_location m_pl;
+public:
+	int meta_get_count(void) const { return 0; }
+	const char *meta_enum_name(int) const { return NULL; }
+	const char *meta_enum_value(int) const { return NULL; }
+	void meta_modify_value(int,const char *) { }
+	void meta_insert(int,const char *,const char *) { }
+	void meta_add(const char *,const char *) { }
+	void meta_remove(int) { }
+	void meta_remove_all(void) { }
+	void info_set(const char *,const char *) { }
+	int info_get_count(void) const { return 0; }
+	const char *info_enum_name(int) const { return NULL; }
+	const char *info_enum_value(int) const { return NULL; }
+	void info_remove(int) { }
+	void info_remove_all(void) { }
+	const class playable_location *get_location(void) const { return &m_pl; }
+	void set_location(const class playable_location *) { }
+	void set_length(double) { }
+	double get_length(void) const { return 0; }
+};
+
 #endif // _MATROSKA_PARSER_H_
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.