Skip to content

Commit

Permalink
MetaDataIO.Write : Exclusively use the value of input tag parameter (…
Browse files Browse the repository at this point in the history
…and not this.tagData) to update the file

Fix certain cases where the fields would not be properly updated internally right after calling IMetaDataIO.Write (NB : no impact on the saved file itself)
  • Loading branch information
Zeugma440 committed Nov 7, 2024
1 parent 79a4322 commit 2a7f8a7
Show file tree
Hide file tree
Showing 18 changed files with 215 additions and 126 deletions.
3 changes: 2 additions & 1 deletion ATL.unit-test/IO/MetaData/MetaIOTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -897,14 +897,15 @@ protected void readExistingTagsOnFile(AudioDataManager theFile, int nbPictures =
byte nbFound = 0;
foreach (PictureInfo pic in meta.EmbeddedPictures)
{
pic.ComputePicHash();
foreach (PictureInfo testPicInfo in testData.EmbeddedPictures)
{
testPicInfo.ComputePicHash();
if ((pic.NativePicCode > -1 && pic.NativePicCode.Equals(testPicInfo.NativePicCode))
|| (pic.NativePicCodeStr != null && pic.NativePicCodeStr.Equals(testPicInfo.NativePicCodeStr, StringComparison.OrdinalIgnoreCase))
)
{
nbFound++;
pic.ComputePicHash();
Assert.AreEqual(testPicInfo.PictureHash, pic.PictureHash);
break;
}
Expand Down
4 changes: 2 additions & 2 deletions ATL/AudioData/IO/Helpers/BextTag.cs
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ public static void FromStream(Stream source, MetaDataIO meta, ReadTagParams read
/// </summary>
/// <param name="meta">Metadata I/O to test with</param>
/// <returns>True if the given Metadata I/O contains data relevant to the Bext format; false if it doesn't</returns>
public static bool IsDataEligible(MetaDataIO meta)
public static bool IsDataEligible(MetaDataHolder meta)
{
if (meta.GeneralDescription.Length > 0) return true;

Expand All @@ -136,7 +136,7 @@ public static bool IsDataEligible(MetaDataIO meta)
/// <param name="isLittleEndian">Endianness to write the size headers with</param>
/// <param name="meta">Metadata to write</param>
/// <returns>The number of written fields</returns>
public static int ToStream(BinaryWriter w, bool isLittleEndian, MetaDataIO meta)
public static int ToStream(BinaryWriter w, bool isLittleEndian, MetaDataHolder meta)
{
IDictionary<string, string> additionalFields = meta.AdditionalFields;
w.Write(Utils.Latin1Encoding.GetBytes(CHUNK_BEXT));
Expand Down
4 changes: 2 additions & 2 deletions ATL/AudioData/IO/Helpers/CartTag.cs
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ public static void FromStream(Stream source, MetaDataIO meta, ReadTagParams read
/// </summary>
/// <param name="meta">Metadata I/O to test with</param>
/// <returns>True if the given Metadata I/O contains data relevant to the Cart format; false if it doesn't</returns>
public static bool IsDataEligible(MetaDataIO meta)
public static bool IsDataEligible(MetaDataHolder meta)
{
return WavHelper.IsDataEligible(meta, "cart.");
}
Expand All @@ -165,7 +165,7 @@ public static bool IsDataEligible(MetaDataIO meta)
/// <param name="isLittleEndian">Endianness to write the size headers with</param>
/// <param name="meta">Metadata to write</param>
/// <returns>The number of written fields</returns>
public static int ToStream(BinaryWriter w, bool isLittleEndian, MetaDataIO meta)
public static int ToStream(BinaryWriter w, bool isLittleEndian, MetaDataHolder meta)
{
IDictionary<string, string> additionalFields = meta.AdditionalFields;
w.Write(Utils.Latin1Encoding.GetBytes(CHUNK_CART));
Expand Down
4 changes: 2 additions & 2 deletions ATL/AudioData/IO/Helpers/CueTag.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public static void FromStream(Stream source, MetaDataIO meta, ReadTagParams read
/// </summary>
/// <param name="meta">Metadata I/O to test with</param>
/// <returns>True if the given Metadata I/O contains data relevant to the Cue-points format; false if it doesn't</returns>
public static bool IsDataEligible(MetaDataIO meta)
public static bool IsDataEligible(MetaDataHolder meta)
{
return WavHelper.IsDataEligible(meta, "cue.");
}
Expand All @@ -68,7 +68,7 @@ public static bool IsDataEligible(MetaDataIO meta)
/// <param name="isLittleEndian">Endianness to write the size headers with</param>
/// <param name="meta">Metadata to write</param>
/// <returns>The number of written fields</returns>
public static int ToStream(BinaryWriter w, bool isLittleEndian, MetaDataIO meta)
public static int ToStream(BinaryWriter w, bool isLittleEndian, MetaDataHolder meta)
{
IDictionary<string, string> additionalFields = meta.AdditionalFields;
w.Write(Utils.Latin1Encoding.GetBytes(CHUNK_CUE));
Expand Down
4 changes: 2 additions & 2 deletions ATL/AudioData/IO/Helpers/DispTag.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ private static int getCfCode(string label)
/// </summary>
/// <param name="meta">Metadata I/O to test with</param>
/// <returns>True if the given Metadata I/O contains data relevant to the Disp format; false if it doesn't</returns>
public static bool IsDataEligible(MetaDataIO meta)
public static bool IsDataEligible(MetaDataHolder meta)
{
return WavHelper.IsDataEligible(meta, "disp.entry");
}
Expand All @@ -105,7 +105,7 @@ public static bool IsDataEligible(MetaDataIO meta)
/// <param name="isLittleEndian">Endianness to write the size headers with</param>
/// <param name="meta">Metadata to write</param>
/// <returns>The number of written fields</returns>
public static int ToStream(BinaryWriter w, bool isLittleEndian, MetaDataIO meta)
public static int ToStream(BinaryWriter w, bool isLittleEndian, MetaDataHolder meta)
{
IDictionary<string, string> additionalFields = meta.AdditionalFields;

Expand Down
4 changes: 2 additions & 2 deletions ATL/AudioData/IO/Helpers/IXmlTag.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@ public static void FromStream(Stream source, MetaDataIO meta, ReadTagParams read
xmlArray.FromStream(source, meta, readTagParams, chunkSize);
}

public static bool IsDataEligible(MetaDataIO meta)
public static bool IsDataEligible(MetaDataHolder meta)
{
return WavHelper.IsDataEligible(meta, "ixml.");
}

public static int ToStream(BinaryWriter w, bool isLittleEndian, MetaDataIO meta)
public static int ToStream(BinaryWriter w, bool isLittleEndian, MetaDataHolder meta)
{
w.Write(Utils.Latin1Encoding.GetBytes(CHUNK_IXML));

Expand Down
14 changes: 7 additions & 7 deletions ATL/AudioData/IO/Helpers/ListTag.cs
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ private static void readLabeledTextSubChunk(Stream source, MetaDataIO meta, int
meta.SetMetaField("adtl.Labels[" + position + "].Text", value, readTagParams.ReadAllMetaFrames);
}

public static bool IsDataEligible(MetaDataIO meta)
public static bool IsDataEligible(MetaDataHolder meta)
{
if (meta.Title.Length > 0) return true;
if (meta.Album.Length > 0) return true;
Expand All @@ -141,17 +141,17 @@ public static bool IsDataEligible(MetaDataIO meta)
return WavHelper.IsDataEligible(meta, "info.") || WavHelper.IsDataEligible(meta, "adtl.");
}

public static int ToStream(BinaryWriter w, bool isLittleEndian, string purpose, MetaDataIO meta)
public static int ToStream(BinaryWriter w, bool isLittleEndian, string purpose, MetaDataHolder tag, MetaDataIO metaIO)
{
IDictionary<string, string> additionalFields = meta.AdditionalFields;
IDictionary<string, string> additionalFields = tag.AdditionalFields;
w.Write(Utils.Latin1Encoding.GetBytes(CHUNK_LIST));

long sizePos = w.BaseStream.Position;
w.Write(0); // Placeholder for chunk size that will be rewritten at the end of the method

w.Write(Utils.Latin1Encoding.GetBytes(purpose));

if (purpose.Equals(PURPOSE_INFO, StringComparison.OrdinalIgnoreCase)) writeInfoPurpose(w, meta);
if (purpose.Equals(PURPOSE_INFO, StringComparison.OrdinalIgnoreCase)) writeInfoPurpose(w, tag, metaIO);
else if (purpose.Equals(PURPOSE_ADTL, StringComparison.OrdinalIgnoreCase)) writeDataListPurpose(w, isLittleEndian, additionalFields);

long finalPos = w.BaseStream.Position;
Expand All @@ -168,7 +168,7 @@ public static int ToStream(BinaryWriter w, bool isLittleEndian, string purpose,
return 14;
}

private static void writeInfoPurpose(BinaryWriter w, MetaDataIO meta)
private static void writeInfoPurpose(BinaryWriter w, MetaDataHolder meta, MetaDataIO metaIO)
{
IDictionary<string, string> additionalFields = meta.AdditionalFields;

Expand All @@ -195,7 +195,7 @@ private static void writeInfoPurpose(BinaryWriter w, MetaDataIO meta)
if (0 == value.Length && additionalFields.TryGetValue("info.ICOP", out var field2)) value = field2;
if (value.Length > 0) writeSizeAndNullTerminatedString("ICOP", value, w, writtenFields);
// Recording date
value = meta.EncodeDate(meta.Date);
value = metaIO.EncodeDate(meta.Date);
if (0 == value.Length && additionalFields.TryGetValue("info.ICRD", out var additionalField2)) value = additionalField2;
if (value.Length > 0) writeSizeAndNullTerminatedString("ICRD", value, w, writtenFields);
// Genre
Expand Down Expand Up @@ -237,7 +237,7 @@ private static void writeInfoPurpose(BinaryWriter w, MetaDataIO meta)
{
var shortKey = key.Substring(5, key.Length - 5).ToUpper();
if (!writtenFields.ContainsKey(key) && additionalFields[key].Length > 0)
writeSizeAndNullTerminatedString(shortKey, meta.FormatBeforeWriting(additionalFields[key]), w, writtenFields);
writeSizeAndNullTerminatedString(shortKey, metaIO.FormatBeforeWriting(additionalFields[key]), w, writtenFields);
}
}

Expand Down
4 changes: 2 additions & 2 deletions ATL/AudioData/IO/Helpers/SampleTag.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,12 @@ public static void FromStream(Stream source, MetaDataIO meta, ReadTagParams read
}
}

public static bool IsDataEligible(MetaDataIO meta)
public static bool IsDataEligible(MetaDataHolder meta)
{
return WavHelper.IsDataEligible(meta, "sample.");
}

public static int ToStream(BinaryWriter w, bool isLittleEndian, MetaDataIO meta)
public static int ToStream(BinaryWriter w, bool isLittleEndian, MetaDataHolder meta)
{
IDictionary<string, string> additionalFields = meta.AdditionalFields;
w.Write(Utils.Latin1Encoding.GetBytes(CHUNK_SAMPLE));
Expand Down
2 changes: 1 addition & 1 deletion ATL/AudioData/IO/Helpers/WavHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ internal static class WavHelper
/// <param name="meta">Metadata I/O to test with</param>
/// <param name="prefix">Prefix to test with</param>
/// <returns>True if the given Metadata I/O contains data relevant to the given prefix; false if it doesn't</returns>
public static bool IsDataEligible(MetaDataIO meta, string prefix)
public static bool IsDataEligible(MetaDataHolder meta, string prefix)
{
return meta.AdditionalFields.Keys.Any(key => key.StartsWith(prefix));
}
Expand Down
4 changes: 2 additions & 2 deletions ATL/AudioData/IO/Helpers/XmpTag.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,12 @@ public static void FromStream(Stream source, MetaDataIO meta, ReadTagParams read
xmlArray.FromStream(source, meta, readTagParams, chunkSize);
}

public static bool IsDataEligible(MetaDataIO meta)
public static bool IsDataEligible(MetaDataHolder meta)
{
return WavHelper.IsDataEligible(meta, "xmp.");
}

public static int ToStream(BinaryWriter w, MetaDataIO meta, bool isLittleEndian = false, bool wavEmbed = false)
public static int ToStream(BinaryWriter w, MetaDataHolder meta, bool isLittleEndian = false, bool wavEmbed = false)
{
if (wavEmbed) w.Write(Utils.Latin1Encoding.GetBytes(CHUNK_XMP));

Expand Down
17 changes: 9 additions & 8 deletions ATL/AudioData/IO/ID3v2.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1472,9 +1472,9 @@ private int writeFrames(TagData tag, BinaryWriter w, Encoding tagEncoding)
}

// Chapters
if (Chapters.Count > 0)
if (tag.Chapters != null && tag.Chapters.Count > 0)
{
nbFrames += writeChapters(w, Chapters, tagEncoding);
nbFrames += writeChapters(w, tag, tagEncoding);
}

// Lyrics
Expand Down Expand Up @@ -1545,30 +1545,31 @@ private static void writeFrameHeader(BinaryWriter w, string frameCode, bool useU
w.Write(StreamUtils.EncodeBEInt16(flags));
}

private int writeChapters(BinaryWriter writer, IList<ChapterInfo> chapters, Encoding tagEncoding)
private int writeChapters(BinaryWriter writer, TagData tag, Encoding tagEncoding)
{
int result;

if (tagHeader.UsesUnsynchronisation)
{
MemoryStream s = new MemoryStream((int)Size);
using BinaryWriter w = new BinaryWriter(s, tagEncoding);
result = writeChaptersInternal(writer, w, chapters, tagEncoding, writer.BaseStream.Position);
result = writeChaptersInternal(writer, w, tag, tagEncoding, writer.BaseStream.Position);
s.Seek(0, SeekOrigin.Begin);
encodeUnsynchronizedStreamTo(s, writer);
}
else
{
result = writeChaptersInternal(writer, writer, chapters, tagEncoding, 0);
result = writeChaptersInternal(writer, writer, tag, tagEncoding, 0);
}

return result;
}

private int writeChaptersInternal(BinaryWriter fileWriter, BinaryWriter frameWriter, IList<ChapterInfo> chapters, Encoding tagEncoding, long frameOffset)
private int writeChaptersInternal(BinaryWriter fileWriter, BinaryWriter frameWriter, TagData tag, Encoding tagEncoding, long frameOffset)
{
Random randomGenerator = null;
long frameSizePos, frameDataPos, finalFramePos;
IList<ChapterInfo> chapters = tag.Chapters;
int result = 0;

// Write a "flat" table of contents, if any CTOC is present in tag
Expand Down Expand Up @@ -1603,8 +1604,8 @@ private int writeChaptersInternal(BinaryWriter fileWriter, BinaryWriter frameWri
}

// CTOC description
if (Utils.ProtectValue(ChaptersTableDescription).Length > 0)
writeTextFrame(frameWriter, "TIT2", ChaptersTableDescription, tagEncoding, "", "", true);
if (Utils.ProtectValue(tag[Field.CHAPTERS_TOC_DESCRIPTION]).Length > 0)
writeTextFrame(frameWriter, "TIT2", tag[Field.CHAPTERS_TOC_DESCRIPTION], tagEncoding, "", "", true);

// Go back to frame size location to write its actual size
finalFramePos = frameWriter.BaseStream.Position;
Expand Down
14 changes: 7 additions & 7 deletions ATL/AudioData/IO/MP4.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1791,7 +1791,7 @@ private int write(TagData tag, BinaryWriter w, string zone)
}
else if (zone.StartsWith(ZONE_MP4_CHPL)) // Nero chapters
{
result = writeNeroChapters(w, Chapters);
result = writeNeroChapters(w, tag.Chapters);
}
else if (zone.StartsWith(ZONE_MP4_XTRA)) // Extra WMA-like fields written by Windows
{
Expand All @@ -1814,25 +1814,25 @@ private int write(TagData tag, BinaryWriter w, string zone)
}
else if (zone.StartsWith(ZONE_MP4_QT_CHAP_NOTREF)) // Write a new tref atom for quicktime chapters
{
result = writeQTChaptersTref(w, qtChapterTextTrackId, qtChapterPictureTrackId, Chapters);
result = writeQTChaptersTref(w, qtChapterTextTrackId, qtChapterPictureTrackId, tag.Chapters);
}
else if (zone.StartsWith(ZONE_MP4_QT_CHAP_CHAP)) // Reference to Quicktime chapter track from an audio/video track
{
result = writeQTChaptersChap(w, qtChapterTextTrackId, qtChapterPictureTrackId, Chapters);
result = writeQTChaptersChap(w, qtChapterTextTrackId, qtChapterPictureTrackId, tag.Chapters);
}
else if (zone.StartsWith(ZONE_MP4_QT_CHAP_TXT_TRAK)) // Quicktime chapter text track
{
if (zone.Equals(ZONE_MP4_QT_CHAP_TXT_TRAK)) // Text track ATL supports -> can be edited
result = writeQTChaptersTrack(w, qtChapterTextTrackId, Chapters, globalTimeScale, Convert.ToUInt32(calculatedDurationMs), true);
result = writeQTChaptersTrack(w, qtChapterTextTrackId, tag.Chapters, globalTimeScale, Convert.ToUInt32(calculatedDurationMs), true);
else return 1; // Other text track ATL doesn't support; needs to appear active
}
else if (zone.StartsWith(ZONE_MP4_QT_CHAP_PIC_TRAK)) // Quicktime chapter picture track
{
result = writeQTChaptersTrack(w, qtChapterPictureTrackId, Chapters, globalTimeScale, Convert.ToUInt32(calculatedDurationMs), false);
result = writeQTChaptersTrack(w, qtChapterPictureTrackId, tag.Chapters, globalTimeScale, Convert.ToUInt32(calculatedDurationMs), false);
}
else if (zone.StartsWith(ZONE_MP4_QT_CHAP_MDAT)) // Quicktime chapter data (text and picture data)
{
result = writeQTChaptersData(w, Chapters);
result = writeQTChaptersData(w, tag.Chapters);
}
else if (zone.StartsWith("uuid.")) // Existing UUID atoms
{
Expand Down Expand Up @@ -2617,7 +2617,7 @@ private int writeUuidFrame(TagData tag, string key, BinaryWriter w)
{
using var mem = new MemoryStream();
using var memW = new BinaryWriter(mem);
XmpTag.ToStream(memW, this);
XmpTag.ToStream(memW, new TagHolder(tag));
data = mem.ToArray();
}
else
Expand Down
13 changes: 7 additions & 6 deletions ATL/AudioData/IO/VGM.cs
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,8 @@ protected override int write(TagData tag, Stream s, string zone)
private int write(TagData tag, BinaryWriter w)
{
byte[] endString = new byte[] { 0, 0 };
int result = 11; // 11 field to write
int result = 11; // 11 fields to write
var holder = new TagHolder(tag);
Encoding unicodeEncoder = Encoding.Unicode;

w.Write(GD3_SIGNATURE);
Expand All @@ -298,14 +299,14 @@ private int write(TagData tag, BinaryWriter w)
var sizePos = w.BaseStream.Position;
w.Write(0);

w.Write(unicodeEncoder.GetBytes(tag[Field.TITLE]));
w.Write(unicodeEncoder.GetBytes(holder.Title));
w.Write(endString); // Strings must be null-terminated
var str = "";
if (AdditionalFields.ContainsKey("TITLE_J")) str = AdditionalFields["TITLE_J"];
w.Write(unicodeEncoder.GetBytes(str));
w.Write(endString);

w.Write(unicodeEncoder.GetBytes(tag[Field.ALBUM]));
w.Write(unicodeEncoder.GetBytes(holder.Album));
w.Write(endString);
str = "";
if (AdditionalFields.ContainsKey("GAME_J")) str = AdditionalFields["GAME_J"];
Expand All @@ -321,22 +322,22 @@ private int write(TagData tag, BinaryWriter w)
w.Write(unicodeEncoder.GetBytes(str));
w.Write(endString);

w.Write(unicodeEncoder.GetBytes(tag[Field.ARTIST]));
w.Write(unicodeEncoder.GetBytes(holder.Artist));
w.Write(endString);
str = "";
if (AdditionalFields.ContainsKey("AUTHOR_J")) str = AdditionalFields["AUTHOR_J"];
w.Write(unicodeEncoder.GetBytes(str));
w.Write(endString);

w.Write(unicodeEncoder.GetBytes(EncodeDate(Date)));
w.Write(unicodeEncoder.GetBytes(EncodeDate(holder.Date)));
w.Write(endString);

str = "";
if (AdditionalFields.ContainsKey("DUMPER")) str = AdditionalFields["DUMPER"];
w.Write(unicodeEncoder.GetBytes(str));
w.Write(endString);

w.Write(unicodeEncoder.GetBytes(tag[Field.COMMENT]));
w.Write(unicodeEncoder.GetBytes(holder.Comment));
w.Write(endString);

w.Write(endString); // Is supposed to be there, according to sample files
Expand Down
Loading

0 comments on commit 2a7f8a7

Please sign in to comment.