private ByteVector RenderUniqueFields() { ByteVector data = new ByteVector(); data.Add(ByteVector.FromString(owner, StringType.Latin1)); data.Add(TextDelimiter(StringType.Latin1)); data.Add(identifier); return data; }
public override void SetCommentPacket (ByteVectorCollection packets, XiphComment comment) { if (packets == null) throw new ArgumentNullException ("packets"); if (comment == null) throw new ArgumentNullException ("comment"); ByteVector data = new ByteVector ((byte) 0x03); data.Add (id); data.Add (comment.Render (true)); if (packets.Count > 1 && PacketType (packets [1]) == 0x03) packets [1] = data; else packets.Insert (1, data); }
private ByteVector RenderPrivateFields() { ByteVector vector = new ByteVector(); vector.Add(ByteVector.FromString(owner, StringType.Latin1)); vector.Add(TextDelimiter(StringType.Latin1)); vector.Add(data); return vector; }
public override ByteVector Render() { ByteVector data = new ByteVector(); foreach (TagLib.Asf.Object obj2 in this.children) { data.Add(obj2.Render()); } data.Insert(0, TagLib.Asf.Object.RenderDWord((uint) data.Count)); data.Insert(0, TagLib.Asf.Object.RenderWord(6)); data.Insert(0, TagLib.Asf.Guid.AsfReserved1.ToByteArray()); return base.Render(data); }
public override ByteVector Render() { ByteVector data = new ByteVector(); uint num = 0; foreach (TagLib.Asf.Object obj2 in this.children) { if (obj2.Guid != TagLib.Asf.Guid.AsfPaddingObject) { data.Add(obj2.Render()); num++; } } long num2 = (data.Count + 30L) - ((long) base.OriginalSize); if (num2 != 0) { data.Add(new PaddingObject((num2 <= 0L) ? ((uint) -num2) : ((uint) 0x1000L)).Render()); num++; } data.Insert(0, this.reserved); data.Insert(0, TagLib.Asf.Object.RenderDWord(num)); return base.Render(data); }
public ByteVector Render() { ByteVector vector = new ByteVector { ByteVector.FromUInt((uint) this.Type) }; ByteVector data = ByteVector.FromString(this.MimeType, StringType.Latin1); vector.Add(ByteVector.FromUInt((uint) data.Count)); vector.Add(data); ByteVector vector3 = ByteVector.FromString(this.Description, StringType.UTF8); vector.Add(ByteVector.FromUInt((uint) vector3.Count)); vector.Add(vector3); vector.Add(ByteVector.FromUInt((uint) this.Width)); vector.Add(ByteVector.FromUInt((uint) this.Height)); vector.Add(ByteVector.FromUInt((uint) this.ColorDepth)); vector.Add(ByteVector.FromUInt((uint) this.IndexedColors)); vector.Add(ByteVector.FromUInt((uint) this.Data.Count)); vector.Add(this.Data); return vector; }
private string CreateDataString (int min_size) { string src = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; ByteVector data = new ByteVector (); for (int i = 0; data.Count < min_size; i++) { int index = i % src.Length; data.Add (src.Substring (index, src.Length - index)); } return data.ToString (); }
/// <summary> /// Overwrites all page headers in a file starting at a /// specified position, shifting the page sequence numbers /// a set amount. /// </summary> /// <param name="file"> /// A <see cref="File" /> object containing the file to /// update. /// </param> /// <param name="position"> /// A <see cref="long" /> value specify at what position to /// start updating. /// </param> /// <param name="shiftTable"> /// A <see cref="T:System.Collections.Generic.IDictionary`2" /// /> object where the key is the serial number of the /// stream to update and the value is the amount to offset /// the page sequence numbers in the stream. /// </param> /// <exception cref="ArgumentNullException"> /// <paramref name="file" /> or <paramref name="shiftTable" /// /> is <see langword="null" />. /// </exception> /// <remarks> /// When the number of pages in a stream changes, all /// subsequent pages in the stream need to have their page /// sequence number update in order to remain valid. /// Additionally, when the page sequence number changes, the /// page needs to have its checksum recomputed. This makes /// for a costly recalculation if large comment data is /// added. /// </remarks> public static void OverwriteSequenceNumbers(File file, long position, IDictionary <uint, int> shiftTable) { if (file == null) { throw new ArgumentNullException("file"); } if (shiftTable == null) { throw new ArgumentNullException("shiftTable"); } // Check to see if there are no changes to be made. bool done = true; foreach (KeyValuePair <uint, int> pair in shiftTable) { if (pair.Value != 0) { done = false; break; } } // If the file is fine, quit. if (done) { return; } while (position < file.Length - 27) { PageHeader header = new PageHeader(file, position); int size = (int)(header.Size + header.DataSize); if (shiftTable.ContainsKey(header.StreamSerialNumber) && shiftTable [header.StreamSerialNumber] != 0) { file.Seek(position); ByteVector page_data = file.ReadBlock(size); ByteVector new_data = ByteVector.FromUInt( (uint)(header.PageSequenceNumber + shiftTable [header.StreamSerialNumber]), false); for (int i = 18; i < 22; i++) { page_data [i] = new_data [i - 18]; } for (int i = 22; i < 26; i++) { page_data [i] = 0; } new_data.Add(ByteVector.FromUInt( page_data.Checksum, false)); file.Seek(position + 18); file.WriteBlock(new_data); } position += size; } }
/// <summary> /// Renders the current instance as a raw ID3v2 header. /// </summary> /// <returns> /// A <see cref="ByteVector" /> object containing the /// rendered header. /// </returns> public ByteVector Render () { ByteVector v = new ByteVector (); v.Add (FileIdentifier); v.Add (MajorVersion); v.Add (RevisionNumber); v.Add ((byte)flags); v.Add (SynchData.FromUInt (TagSize)); return v; }
public ByteVector Render () { ByteVector data = new ByteVector (); data.Add ("OggS"); data.Add (_version); // stream structure version data.Add ((byte) _flags); data.Add (ByteVector.FromULong (_absolute_granular_position, false)); data.Add (ByteVector.FromUInt (_stream_serial_number, false)); data.Add (ByteVector.FromUInt ((uint) _page_sequence_number, false)); data.Add (new ByteVector (4, 0)); // checksum, to be filled in later. ByteVector page_segments = LacingValues; data.Add ((byte) page_segments.Count); data.Add (page_segments); return data; }
/// <summary> /// Renders the current instance, including its children, to /// a new <see cref="ByteVector" /> object, preceeding the /// contents with a specified block of data. /// </summary> /// <param name="topData"> /// A <see cref="ByteVector" /> object containing box /// specific header data to preceed the content. /// </param> /// <returns> /// A <see cref="ByteVector" /> object containing the /// rendered version of the current instance. /// </returns> protected virtual ByteVector Render (ByteVector topData) { bool free_found = false; ByteVector output = new ByteVector (); if (Children != null) foreach (Box box in Children) if (box.GetType () == typeof ( IsoFreeSpaceBox)) free_found = true; else output.Add (box.Render ()); else if (Data != null) output.Add (Data); // If there was a free, don't take it away, and let meta // be a special case. if (free_found || BoxType == Mpeg4.BoxType.Meta) { long size_difference = DataSize - output.Count; // If we have room for free space, add it so we // don't have to resize the file. if (header.DataSize != 0 && size_difference >= 8) output.Add ((new IsoFreeSpaceBox ( size_difference)).Render ()); // If we're getting bigger, get a lot bigger so // we might not have to again. else output.Add ((new IsoFreeSpaceBox (2048 )).Render ()); } // Adjust the header's data size to match the content. header.DataSize = topData.Count + output.Count; // Render the full box. output.Insert (0, topData); output.Insert (0, header.Render ()); return output; }
/// <summary> /// Searches for an audio header in a <see cref="TagLib.File" /// /> starting at a specified position and searching through /// a specified number of bytes. /// </summary> /// <param name="header"> /// A <see cref="AudioHeader" /> object in which the found /// header will be stored. /// </param> /// <param name="file"> /// A <see cref="TagLib.File" /> object to search. /// </param> /// <param name="position"> /// A <see cref="long" /> value specifying the seek position /// in <paramref name="file" /> at which to start searching. /// </param> /// <param name="length"> /// A <see cref="int" /> value specifying the maximum number /// of bytes to search before aborting. /// </param> /// <returns> /// A <see cref="bool" /> value indicating whether or not a /// header was found. /// </returns> /// <exception cref="ArgumentNullException"> /// <paramref name="file" /> is <see langword="null" />. /// </exception> public static bool Find(out AudioHeader header, TagLib.File file, long position, int length) { if (file == null) { throw new ArgumentNullException(nameof(file)); } long end = position + length; header = Unknown; file.Seek(position); ByteVector buffer = file.ReadBlock(3); if (buffer.Count < 3) { return(false); } do { file.Seek(position + 3); buffer = buffer.Mid(buffer.Count - 3); buffer.Add(file.ReadBlock( (int)TagLib.File.BufferSize)); for (int i = 0; i < buffer.Count - 3 && (length < 0 || position + i < end); i++) { if (buffer[i] == 0xFF && buffer[i + 1] >= 0xF0) // 0xFFF { try { BitStream bits = new BitStream(buffer.Mid(i, 7).Data); // 12 bits sync header bits.ReadInt32(12); // 1 bit mpeg 2/4 bits.ReadInt32(1); // 2 bits layer bits.ReadInt32(2); // 1 bit protection absent bits.ReadInt32(1); // 2 bits profile object type bits.ReadInt32(2); // 4 bits sampling frequency index int samplerateindex = bits.ReadInt32(4); if (samplerateindex >= sample_rates.Length) { return(false); } long samplerate = sample_rates[samplerateindex]; // 1 bit private bit bits.ReadInt32(1); // 3 bits channel configuration int channelconfigindex = bits.ReadInt32(3); if (channelconfigindex >= channels.Length) { return(false); } // 4 copyright bits bits.ReadInt32(4); // 13 bits frame length long framelength = bits.ReadInt32(13); // double check framelength if (framelength < 7) { return(false); } // 11 bits buffer fullness bits.ReadInt32(11); // 2 bits number of raw data blocks in frame int numberofframes = bits.ReadInt32(2) + 1; long numberofsamples = numberofframes * 1024; long bitrate = framelength * 8 * samplerate / numberofsamples; header = new AudioHeader(channels[channelconfigindex], (int)bitrate, (int)samplerate, (int)numberofsamples, numberofframes); return(true); } catch (CorruptFileException) { } } } position += TagLib.File.BufferSize; } while (buffer.Count > 3 && (length < 0 || position < end)); return(false); }
/// <summary> /// Renders the current instance to a <see cref="ByteVector"/> /// </summary> /// <param name="is_bigendian"> /// A <see cref="System.Boolean"/> indicating the endianess for rendering. /// </param> /// <param name="offset"> /// A <see cref="System.UInt32"/> with the offset, the data is stored. /// </param> /// <param name="type"> /// A <see cref="System.UInt16"/> the ID of the type, which is rendered /// </param> /// <param name="count"> /// A <see cref="System.UInt32"/> with the count of the values which are /// rendered. /// </param> /// <returns> /// A <see cref="ByteVector"/> with the rendered data. /// </returns> public ByteVector Render (bool is_bigendian, uint offset, out ushort type, out uint count) { type = (ushort) IFDEntryType.SRational; count = 1; ByteVector data = new ByteVector (); data.Add (ByteVector.FromInt (Value.Numerator, is_bigendian)); data.Add (ByteVector.FromInt (Value.Denominator, is_bigendian)); return data; }
/// <summary> /// Renders the values in the current instance into field /// data for a specified version. /// </summary> /// <param name="version"> /// A <see cref="byte" /> indicating the ID3v2 version the /// field data is to be encoded in. /// </param> /// <returns> /// A <see cref="ByteVector" /> object containing the /// rendered field data. /// </returns> protected override ByteVector RenderFields (byte version) { if (raw_data != null && raw_version == version) return raw_data; StringType encoding = CorrectEncoding (TextEncoding, version); ByteVector data = new ByteVector (); data.Add ((byte) encoding); if (version == 2) { switch (MimeType) { case "image/png": data.Add ("PNG"); break; case "image/jpeg": data.Add ("JPG"); break; default: data.Add ("XXX"); break; } } else { data.Add (ByteVector.FromString (MimeType, StringType.Latin1)); data.Add (ByteVector.TextDelimiter ( StringType.Latin1)); } data.Add ((byte) type); data.Add (ByteVector.FromString (Description, encoding)); data.Add (ByteVector.TextDelimiter (encoding)); data.Add (this.data); return data; }
/// <summary> /// Renders the current instance, encoded in a specified /// ID3v2 version. /// </summary> /// <param name="version"> /// A <see cref="byte" /> value specifying the version of /// ID3v2 to use when encoding the current instance. /// </param> /// <returns> /// A <see cref="ByteVector" /> object containing the /// rendered version of the current instance. /// </returns> /// <exception cref="NotImplementedException"> /// The current instance uses some feature that cannot be /// implemented in the specified ID3v2 version, or uses a /// feature, such as encryption or compression, which is not /// yet implemented in the library. /// </exception> public virtual ByteVector Render(byte version) { // Remove flags that are not supported by older versions // of ID3v2. if (version < 4) { Flags &= ~(FrameFlags.DataLengthIndicator | FrameFlags.Unsynchronisation); } if (version < 3) { Flags &= ~(FrameFlags.Compression | FrameFlags.Encryption | FrameFlags.FileAlterPreservation | FrameFlags.GroupingIdentity | FrameFlags.ReadOnly | FrameFlags.TagAlterPreservation); } ByteVector field_data = RenderFields(version); // If we don't have any content, don't render anything. // This will cause the frame to not be rendered. if (field_data.Count == 0) { return(new ByteVector()); } ByteVector front_data = new ByteVector(); if ((Flags & (FrameFlags.Compression | FrameFlags.DataLengthIndicator)) != 0) { front_data.Add(ByteVector.FromUInt((uint) field_data.Count)); } if ((Flags & FrameFlags.GroupingIdentity) != 0) { front_data.Add(group_id); } if ((Flags & FrameFlags.Encryption) != 0) { front_data.Add(encryption_id); } // FIXME: Implement compression. if ((Flags & FrameFlags.Compression) != 0) { throw new NotImplementedException( "Compression not yet supported"); } // FIXME: Implement encryption. if ((Flags & FrameFlags.Encryption) != 0) { throw new NotImplementedException( "Encryption not yet supported"); } if ((Flags & FrameFlags.Unsynchronisation) != 0) { SynchData.UnsynchByteVector(field_data); } if (front_data.Count > 0) { field_data.Insert(0, front_data); } header.FrameSize = (uint)field_data.Count; ByteVector header_data = header.Render(version); header_data.Add(field_data); return(header_data); }
public static async Task HandleFile(FileInfo file, string language) { var fileName = Path.GetFileNameWithoutExtension(file.FullName); Console.WriteLine("Processing File: '{0}'", file.FullName); var movies = await SearchForMovie(fileName, language); Console.WriteLine("Which Movie is this file? (enter -1 to skip)"); var count = 1; foreach (var movie in movies.Results) { Console.WriteLine(" [{0}] {1} - {2} - https://www.themoviedb.org/movie/{3}", count++, GetDateTime(movie.ReleaseDate).Year, movie.Title, movie.Id ); } var movieNumber = -1; var userInput = Console.ReadLine(); int.TryParse(userInput, out movieNumber); var index = movieNumber - 1; if (index < 0 || index > movies.Results.Count() - 1) { Console.WriteLine("Not renaming '{0}'", fileName); } else { var searchMovie = movies.Results.ToArray()[index]; var fullMovie = await GetMovie(searchMovie.Id, language); using (TagLib.File tagFile = TagLib.File.Create(file.FullName, "video/mp4", ReadStyle.Average)) { TagLib.Mpeg4.AppleTag customTag = (TagLib.Mpeg4.AppleTag)tagFile.GetTag(TagLib.TagTypes.Apple, true); // name customTag.Title = fullMovie.Title; // STIK || Media Type Tag customTag.ClearData("stik"); var stikVector = new TagLib.ByteVector(); stikVector.Add((byte)9); customTag.SetData("stik", stikVector, (int)TagLib.Mpeg4.AppleDataBox.FlagType.ContainsData); // Short Description customTag.ClearData("desc"); customTag.SetText("desc", ToShortDescription(fullMovie.Overview)); // Long Description customTag.ClearData("ldes"); customTag.SetText("ldes", fullMovie.Overview); // Release Date YYYY-MM-DD var releaseDate = GetDateTime(fullMovie.ReleaseDate); customTag.Year = (uint)releaseDate.Year; customTag.ClearData("tdrl"); customTag.SetText("tdrl", fullMovie.Overview); // Genre var mainGenre = fullMovie.Genres.Select(g => g.Name).First(); customTag.Genres = new string[] { mainGenre }; // Cast / Actors customTag.Performers = fullMovie.Credits.Cast.Select(c => c.Name).ToArray(); // HD Video //customTag.ClearData("hdvd"); var inputFile = new MediaFile { Filename = file.FullName }; using (var engine = new Engine()) { engine.GetMetadata(inputFile); } if (isHd(inputFile.Metadata.VideoData.FrameSize)) { var hdvdVector = new ByteVector(); hdvdVector.Add(Convert.ToByte(true)); customTag.SetData("hdvd", hdvdVector, (int)TagLib.Mpeg4.AppleDataBox.FlagType.ContainsData); } // Artwork / Poster if (!String.IsNullOrWhiteSpace(fullMovie.Poster)) { Console.WriteLine(" getting movie poster"); var artworkUrl = "http://image.tmdb.org/t/p/original" + fullMovie.Poster; using (var client = new HttpClient()) { var response = await client.GetAsync(artworkUrl); var bytes = await response.Content.ReadAsByteArrayAsync(); tagFile.Tag.Pictures = new IPicture[] { new TagLib.Picture(bytes) }; } } tagFile.Save(); } var newFileName = SanitizeFileName(fullMovie.Title) + Path.GetExtension(file.FullName); var folder = ConfigurationManager.AppSettings["to"]; var newPath = Path.Combine(folder, newFileName); Console.WriteLine(" moving file to {0}", newPath); file.MoveTo(newPath); } Console.WriteLine("========================================================="); }
/// <summary> /// Renders the current instance as a raw Flac picture. /// </summary> /// <returns> /// A <see cref="ByteVector" /> object containing the /// rendered version of the current instance. /// </returns> public ByteVector Render() { ByteVector data = new ByteVector(); data.Add(ByteVector.FromUInt((uint)Type)); ByteVector mime_data = ByteVector.FromString(MimeType, StringType.Latin1); data.Add(ByteVector.FromUInt((uint)mime_data.Count)); data.Add(mime_data); ByteVector decription_data = ByteVector.FromString( Description, StringType.UTF8); data.Add(ByteVector.FromUInt((uint) decription_data.Count)); data.Add(decription_data); data.Add(ByteVector.FromUInt((uint)Width)); data.Add(ByteVector.FromUInt((uint)Height)); data.Add(ByteVector.FromUInt((uint)ColorDepth)); data.Add(ByteVector.FromUInt((uint)IndexedColors)); data.Add(ByteVector.FromUInt((uint)Data.Count)); data.Add(Data); return(data); }
/// <summary> /// Saves the changes made in the current instance to the /// file it represents. /// </summary> public override void Save() { // Boilerplate PreSave(); Mode = AccessMode.Write; try { var data = new ByteVector(); // Add the ID3 chunk and ID32 tag to the vector if (tag != null) { ByteVector tag_data = tag.Render(); if (tag_data.Count > 10) { if (tag_data.Count % 2 == 1) { tag_data.Add(0); } data.Add("ID3 "); data.Add(ByteVector.FromUInt((uint)tag_data.Count, true)); data.Add(tag_data); } } Read(false, ReadStyle.None, out var aiff_size, out var tag_start, out var tag_end); // If tagging info cannot be found, place it at // the end of the file. if (tag_start < 12 || tag_end < tag_start) { tag_start = tag_end = Length; } int length = (int)(tag_end - tag_start + 8); // Insert the tagging data. Insert(data, tag_start, length); // If the data size changed update the aiff size. if (data.Count - length != 0 && tag_start <= aiff_size) { // Depending, if a Tag has been added or removed, // the length needs to be adjusted if (tag == null) { length -= 16; } else { length -= 8; } Insert(ByteVector.FromUInt((uint)(aiff_size + data.Count - length), true), 4, 4); } // Update the tag types. TagTypesOnDisk = TagTypes; } finally { Mode = AccessMode.Closed; } }
/// <summary> /// Renders the current instance as a raw ASF object. /// </summary> /// <returns> /// A <see cref="ByteVector" /> object containing the /// rendered version of the current instance. /// </returns> public override ByteVector Render() { ByteVector output = new ByteVector (); uint child_count = 0; foreach (Object child in children) if (child.Guid != Asf.Guid.AsfPaddingObject) { output.Add (child.Render ()); child_count ++; } long size_diff = (long) output.Count + 30 - (long) OriginalSize; if (size_diff != 0) { PaddingObject obj = new PaddingObject ((uint) (size_diff > 0 ? 4096 : - size_diff)); output.Add (obj.Render ()); child_count ++; } output.Insert (0, reserved); output.Insert (0, RenderDWord (child_count)); return Render (output); }
/// <summary> /// Saves the changes made in the current instance to the /// file it represents. /// </summary> public override void Save() { Mode = AccessMode.Write; try { // Update the tags at the beginning of the file. long metadata_start = StartTag.Write (); long metadata_end; // Get all the blocks, but don't read the data for ones // we're filling with stored data. IList<Block> old_blocks = ReadBlocks (ref metadata_start, out metadata_end, BlockMode.Blacklist, BlockType.XiphComment, BlockType.Picture); // Create new vorbis comments is they don't exist. GetTag (TagTypes.Xiph, true); // Create new blocks and add the basics. List<Block> new_blocks = new List<Block> (); new_blocks.Add (old_blocks [0]); // Add blocks we don't deal with from the file. foreach (Block block in old_blocks) if (block.Type != BlockType.StreamInfo && block.Type != BlockType.XiphComment && block.Type != BlockType.Picture && block.Type != BlockType.Padding) new_blocks.Add (block); new_blocks.Add (new Block (BlockType.XiphComment, (GetTag (TagTypes.Xiph, true) as Ogg.XiphComment).Render (false))); foreach (IPicture picture in metadata.Pictures) { if (picture == null) continue; new_blocks.Add (new Block (BlockType.Picture, new Picture (picture).Render ())); } // Get the length of the blocks. long length = 0; foreach (Block block in new_blocks) length += block.TotalSize; // Find the padding size to avoid trouble. If that fails // make some. long padding_size = metadata_end - metadata_start - BlockHeader.Size - length; if (padding_size < 0) padding_size = 1024 * 4; // Add a padding block. if (padding_size != 0) new_blocks.Add (new Block (BlockType.Padding, new ByteVector ((int) padding_size))); // Render the blocks. ByteVector block_data = new ByteVector (); for (int i = 0; i < new_blocks.Count; i ++) block_data.Add (new_blocks [i].Render ( i == new_blocks.Count - 1)); // Update the blocks. Insert (block_data, metadata_start, metadata_end - metadata_start); // Update the tags at the end of the file. EndTag.Write (); TagTypesOnDisk = TagTypes; } finally { Mode = AccessMode.Closed; } }
/// <summary> /// Renders the current instance as an APEv2 item. /// </summary> /// <returns> /// A <see cref="ByteVector" /> object containing the /// rendered version of the current instance. /// </returns> public ByteVector Render () { uint flags = (uint) ((ReadOnly) ? 1 : 0) | ((uint) Type << 1); if (IsEmpty) return new ByteVector (); ByteVector result = null; if (type == ItemType.Binary) { if (text == null && data != null) result = data; } if (result == null && text != null) { result = new ByteVector (); for (int i = 0; i < text.Length; i ++) { if (i != 0) result.Add ((byte) 0); result.Add (ByteVector.FromString ( text [i], StringType.UTF8)); } } // If no data is stored, don't write the item. if (result == null || result.Count == 0) return new ByteVector (); ByteVector output = new ByteVector (); output.Add (ByteVector.FromUInt ((uint) result.Count, false)); output.Add (ByteVector.FromUInt (flags, false)); output.Add (ByteVector.FromString (key, StringType.UTF8)); output.Add ((byte) 0); output.Add (result); size_on_disk = output.Count; return output; }
protected override ByteVector RenderFields (byte version) { if (raw_data != null && raw_version == version) return raw_data; StringType encoding = CorrectEncoding (TextEncoding, version); ByteVector v = new ByteVector ((byte) encoding); string [] text = text_fields; bool txxx = FrameId == FrameType.TXXX; if (version > 3 || txxx) { if (txxx) { if (text.Length == 0) text = new string [] {null, null}; else if (text.Length == 1) text = new string [] {text [0], null}; } for (int i = 0; i < text.Length; i++) { // Since the field list is null // delimited, if this is not the first // element in the list, append the // appropriate delimiter for this // encoding. if (i != 0) v.Add (ByteVector.TextDelimiter ( encoding)); if (text [i] != null) v.Add (ByteVector.FromString ( text [i], encoding)); } } else if (FrameId == FrameType.TCON) { byte id; bool prev_value_indexed = true; StringBuilder data = new StringBuilder (); foreach (string s in text) { if (!prev_value_indexed) { data.Append ("/").Append (s); continue; } if (prev_value_indexed = byte.TryParse (s, out id)) data.AppendFormat ( CultureInfo.InvariantCulture, "({0})", id); else data.Append (s); } v.Add (ByteVector.FromString (data.ToString (), encoding)); } else { v.Add (ByteVector.FromString ( string.Join ("/", text), encoding)); } return v; }
/// <summary> /// Saves the changes made in the current instance to the /// file it represents. /// </summary> public override void Save () { Mode = AccessMode.Write; try { long end; List<Page> pages = new List<Page> (); Dictionary<uint, Bitstream> streams = ReadStreams (pages, out end); Dictionary<uint, Paginator> paginators = new Dictionary<uint, Paginator> (); List<List<Page>> new_pages = new List<List<Page>> (); Dictionary<uint, int> shifts = new Dictionary<uint, int> (); foreach (Page page in pages) { uint id = page.Header.StreamSerialNumber; if (!paginators.ContainsKey (id)) paginators.Add (id, new Paginator ( streams [id].Codec)); paginators [id].AddPage (page); } foreach (uint id in paginators.Keys) { paginators [id].SetComment ( tag.GetComment (id)); int shift; new_pages.Add (new List<Page> ( paginators [id] .Paginate (out shift))); shifts.Add (id, shift); } ByteVector output = new ByteVector (); bool empty; do { empty = true; foreach (List<Page> stream_pages in new_pages) { if (stream_pages.Count == 0) continue; output.Add (stream_pages [0].Render ()); stream_pages.RemoveAt (0); if (stream_pages.Count != 0) empty = false; } } while (!empty); Insert (output, 0, end); InvariantStartPosition = output.Count; InvariantEndPosition = Length; TagTypesOnDisk = TagTypes; Page.OverwriteSequenceNumbers (this, output.Count, shifts); } finally { Mode = AccessMode.Closed; } }
/// <summary> /// Saves the changes made in the current instance to the /// file it represents. /// </summary> public override void Save() { Mode = AccessMode.Write; try { ByteVector data = new ByteVector(); // Add the ID3 chunk and ID32 tag to the vector if (tag != null) { ByteVector tag_data = tag.Render(); if (tag_data.Count > 10) { if (tag_data.Count%2 == 1) tag_data.Add(0); data.Add("ID3 "); data.Add(ByteVector.FromUInt( (uint) tag_data.Count, true)); data.Add(tag_data); } } // Read the file to determine the current AIFF // size and the area tagging is in. uint aiff_size; long tag_start, tag_end; Read(false, ReadStyle.None, out aiff_size, out tag_start, out tag_end); // If tagging info cannot be found, place it at // the end of the file. if (tag_start < 12 || tag_end < tag_start) tag_start = tag_end = Length; int length = (int) (tag_end - tag_start + 8); // Insert the tagging data. Insert(data, tag_start, length); // If the data size changed update the aiff size. if (data.Count - length != 0 && tag_start <= aiff_size) { // Depending, if a Tag has been added or removed, // the length needs to be adjusted if (tag == null) { length -= 16; } else { length -= 8; } Insert(ByteVector.FromUInt((uint) (aiff_size + data.Count - length), true), 4, 4); } // Update the tag types. TagTypesOnDisk = TagTypes; } finally { Mode = AccessMode.Closed; } }
public override void Save () { Mode = AccessMode.Write; try { ByteVector data = new ByteVector (); if (id32_tag != null) { ByteVector tag_data = id32_tag.Render (); if (tag_data.Count > 10) { if (tag_data.Count % 2 == 1) tag_data.Add (0); data.Add ("ID32"); data.Add (ByteVector.FromUInt ( (uint) tag_data.Count, false)); data.Add (tag_data); } } if (info_tag != null) data.Add (info_tag.RenderEnclosed ()); if (mid_tag != null) data.Add (mid_tag.RenderEnclosed ()); if (divx_tag != null && !divx_tag.IsEmpty) { ByteVector tag_data = divx_tag.Render (); data.Add ("IDVX"); data.Add (ByteVector.FromUInt ( (uint) tag_data.Count, false)); data.Add (tag_data); } uint riff_size; long tag_start, tag_end; Read (false, ReadStyle.None, out riff_size, out tag_start, out tag_end); if (tag_start < 12 || tag_end < tag_start) tag_start = tag_end = Length; int length = (int)(tag_end - tag_start); int padding_size = length - data.Count - 8; if (padding_size < 0) padding_size = 1024; data.Add ("JUNK"); data.Add (ByteVector.FromUInt ( (uint)padding_size, false)); data.Add (new ByteVector (padding_size)); Insert (data, tag_start, length); if (data.Count - length != 0 && tag_start <= riff_size) Insert (ByteVector.FromUInt ((uint) (riff_size + data.Count - length), false), 4, 4); TagTypesOnDisk = TagTypes; } finally { Mode = AccessMode.Closed; } }
/// <summary> /// Constructs a <see cref="EBMLElement" /> parsing from provided /// file data. /// </summary> /// <param name="_file"><see cref="File" /> instance to read from.</param> /// <param name="position">Position to start reading from.</param> public EBMLElement(Matroska.File _file, ulong position) { if (_file == null) { throw new ArgumentNullException("file"); } if (position > (ulong)(_file.Length - 4)) { throw new ArgumentOutOfRangeException("position"); } // Keep a reference to the file file = _file; file.Seek((long)position); // Get the header byte ByteVector vector = file.ReadBlock(1); Byte header_byte = vector [0]; // Define a mask Byte mask = 0x80, id_length = 1; // Figure out the size in bytes while (id_length <= 4 && (header_byte & mask) == 0) { id_length++; mask >>= 1; } if (id_length > 4) { throw new CorruptFileException("invalid EBML id size"); } // Now read the rest of the EBML ID if (id_length > 1) { vector.Add(file.ReadBlock(id_length - 1)); } ebml_id = vector.ToUInt(); vector.Clear(); // Get the size length vector = file.ReadBlock(1); header_byte = vector [0]; mask = 0x80; Byte size_length = 1; // Iterate through various possibilities while (size_length <= 8 && (header_byte & mask) == 0) { size_length++; mask >>= 1; } if (size_length > 8) { throw new CorruptFileException("invalid EBML element size"); } // Clear the marker bit vector [0] &= (Byte)(mask - 1); // Now read the rest of the EBML element size if (size_length > 1) { vector.Add(file.ReadBlock(size_length - 1)); } ebml_size = vector.ToULong(); offset = position; data_offset = offset + id_length + size_length; }
public override ByteVector Render (byte version) { if (version != 3 || FrameId != FrameType.TDRC) return base.Render (version); string text = ToString (); if (text.Length < 10 || text [4] != '-' || text [7] != '-') return base.Render (version); ByteVector output = new ByteVector (); TextInformationFrame f; f = new TextInformationFrame (FrameType.TYER, encoding); f.Text = new string [] {text.Substring (0, 4)}; output.Add (f.Render (version)); f = new TextInformationFrame (FrameType.TDAT, encoding); f.Text = new string [] { text.Substring (5, 2) + text.Substring (8, 2) }; output.Add (f.Render (version)); if (text.Length < 16 || text [10] != 'T' || text [13] != ':') return output; f = new TextInformationFrame (FrameType.TIME, encoding); f.Text = new string [] { text.Substring (11, 2) + text.Substring (14, 2) }; output.Add (f.Render (version)); return output; }
/// <summary> /// Renders the IFD to an ByteVector where the offset of the IFD /// itself is <paramref name="ifd_offset"/> and all offsets /// contained in the IFD are adjusted accroding it. /// </summary> /// <param name="directory"> /// A <see cref="IFDDirectory"/> with the directory to render. /// </param> /// <param name="ifd_offset"> /// A <see cref="System.UInt32"/> with the offset of the IFD /// </param> /// <param name="last"> /// A <see cref="System.Boolean"/> which is true, if the IFD is /// the last one, i.e. the offset to the next IFD, which is /// stored inside the IFD, is 0. If the value is false, the /// offset to the next IFD is set that it starts directly after /// the current one. /// </param> /// <returns> /// A <see cref="ByteVector"/> with the rendered IFD. /// </returns> private ByteVector RenderIFD(IFDDirectory directory, uint ifd_offset, bool last) { if (directory.Count > (int)UInt16.MaxValue) throw new Exception (String.Format ("Directory has too much entries: {0}", directory.Count)); // Remove empty SUB ifds. var tags = new List<ushort> (directory.Keys); foreach (var tag in tags) { var entry = directory [tag]; if (entry is SubIFDEntry && (entry as SubIFDEntry).ChildCount == 0) { directory.Remove (tag); } } ushort entry_count = (ushort) directory.Count; // ifd_offset + size of entry_count + entries + next ifd offset uint data_offset = ifd_offset + 2 + 12 * (uint) entry_count + 4; // store the entries itself ByteVector entry_data = new ByteVector (); // store the data referenced by the entries ByteVector offset_data = new ByteVector (); entry_data.Add (ByteVector.FromUShort (entry_count, is_bigendian)); foreach (IFDEntry entry in directory.Values) RenderEntryData (entry, entry_data, offset_data, data_offset); if (last) entry_data.Add ("\0\0\0\0"); else entry_data.Add (ByteVector.FromUInt ((uint) (data_offset + offset_data.Count), is_bigendian)); if (data_offset - ifd_offset != entry_data.Count) throw new Exception (String.Format ("Expected IFD data size was {0} but is {1}", data_offset - ifd_offset, entry_data.Count)); entry_data.Add (offset_data); return entry_data; }
/// <summary> /// Renders the values in the current instance into field /// data for a specified version. /// </summary> /// <param name="version"> /// A <see cref="byte" /> indicating the ID3v2 version the /// field data is to be encoded in. /// </param> /// <returns> /// A <see cref="ByteVector" /> object containing the /// rendered field data. /// </returns> protected override ByteVector RenderFields(byte version) { StringType encoding = CorrectEncoding (TextEncoding, version); ByteVector v = new ByteVector(); v.Add ((byte) encoding); v.Add (ByteVector.FromString (Language, StringType.Latin1)); v.Add (ByteVector.FromString (description, encoding)); v.Add (ByteVector.TextDelimiter(encoding)); v.Add (ByteVector.FromString (text, encoding)); return v; }
/// <summary> /// Renders the current instance to a <see cref="ByteVector"/>. /// </summary> /// <returns> /// A <see cref="ByteVector"/> containing the rendered IFD. /// </returns> public ByteVector Render() { ByteVector ifd_data = new ByteVector (); uint current_offset = ifd_offset; var directories = structure.directories; for (int index = 0; index < directories.Count; index++) { ByteVector data = RenderIFD (directories [index], current_offset, index == directories.Count - 1); current_offset += (uint) data.Count; ifd_data.Add (data); } return ifd_data; }
/// <summary> /// Renders the current instance as a raw ASF Description /// Record. /// </summary> /// <returns> /// A <see cref="ByteVector" /> object containing the /// rendered version of the current instance. /// </returns> public ByteVector Render () { ByteVector value = null; switch (type) { case DataType.Unicode: value = Object.RenderUnicode (strValue); break; case DataType.Bytes: value = byteValue; break; case DataType.Bool: case DataType.DWord: value = Object.RenderDWord ((uint) longValue); break; case DataType.QWord: value = Object.RenderQWord (longValue); break; case DataType.Word: value = Object.RenderWord ((ushort) longValue); break; case DataType.Guid: value = guidValue.ToByteArray (); break; default: return null; } ByteVector name = Object.RenderUnicode (this.name); ByteVector output = new ByteVector (); output.Add (Object.RenderWord (lang_list_index)); output.Add (Object.RenderWord (stream_number)); output.Add (Object.RenderWord ((ushort) name.Count)); output.Add (Object.RenderWord ((ushort) type)); output.Add (Object.RenderDWord ((uint) value.Count)); output.Add (name); output.Add (value); return output; }
/// <summary> /// Renders the tags contained in the current instance. /// </summary> /// <returns> /// A <see cref="ByteVector" /> object containing the /// physical representation of the tags stored in the current /// instance. /// </returns> /// <remarks> /// The tags are rendered in the order that they are stored /// in the current instance. /// </remarks> public ByteVector Render() { ByteVector data = new ByteVector (); foreach (TagLib.Tag t in Tags) { if (t is TagLib.Ape.Tag) data.Add ((t as TagLib.Ape.Tag).Render ()); else if (t is TagLib.Id3v2.Tag) data.Add ((t as TagLib.Id3v2.Tag).Render ()); else if (t is TagLib.Id3v1.Tag) data.Add ((t as TagLib.Id3v1.Tag).Render ()); } return data; }
/// <summary> /// Renders the current instance as a raw ID3v1 tag. /// </summary> /// <returns> /// A <see cref="ByteVector" /> object containing the /// rendered tag. /// </returns> public ByteVector Render () { ByteVector data = new ByteVector (); data.Add (FileIdentifier); data.Add (string_handler.Render (title ).Resize (30)); data.Add (string_handler.Render (artist ).Resize (30)); data.Add (string_handler.Render (album ).Resize (30)); data.Add (string_handler.Render (year ).Resize ( 4)); data.Add (string_handler.Render (comment).Resize (28)); data.Add ((byte) 0); data.Add (track); data.Add (genre); return data; }
/// <summary> /// Renders the current instance as a raw Flac picture. /// </summary> /// <returns> /// A <see cref="ByteVector" /> object containing the /// rendered version of the current instance. /// </returns> public ByteVector Render() { ByteVector data = new ByteVector (); data.Add (ByteVector.FromUInt ((uint) Type)); ByteVector mime_data = ByteVector.FromString (MimeType, StringType.Latin1); data.Add (ByteVector.FromUInt ((uint) mime_data.Count)); data.Add (mime_data); ByteVector decription_data = ByteVector.FromString ( Description, StringType.UTF8); data.Add (ByteVector.FromUInt ((uint) decription_data.Count)); data.Add (decription_data); data.Add (ByteVector.FromUInt ((uint) Width)); data.Add (ByteVector.FromUInt ((uint) Height)); data.Add (ByteVector.FromUInt ((uint) ColorDepth)); data.Add (ByteVector.FromUInt ((uint) IndexedColors)); data.Add (ByteVector.FromUInt ((uint) Data.Count)); data.Add (Data); return data; }
/// <summary> /// Saves the changes made in the current instance to the /// file it represents. /// </summary> public override void Save() { Mode = AccessMode.Write; try { ByteVector data = new ByteVector (); // Enclose the Id3v2 tag in an "ID32" item and // embed it as the first tag. if (id32_tag != null) { ByteVector tag_data = id32_tag.Render (); if (tag_data.Count > 10) { if (tag_data.Count % 2 == 1) tag_data.Add (0); data.Add ("ID32"); data.Add (ByteVector.FromUInt ( (uint) tag_data.Count, false)); data.Add (tag_data); } } // Embed "INFO" as the second tag. if (info_tag != null) data.Add (info_tag.RenderEnclosed ()); // Embed "MID " as the third tag. if (mid_tag != null) data.Add (mid_tag.RenderEnclosed ()); // Embed the DivX tag in "IDVX and embed it as // the fourth tag. if (divx_tag != null && !divx_tag.IsEmpty) { ByteVector tag_data = divx_tag.Render (); data.Add ("IDVX"); data.Add (ByteVector.FromUInt ( (uint) tag_data.Count, false)); data.Add (tag_data); } // Read the file to determine the current RIFF // size and the area tagging does in. uint riff_size; long tag_start, tag_end; Read (false, ReadStyle.None, out riff_size, out tag_start, out tag_end); // If tagging info cannot be found, place it at // the end of the file. if (tag_start < 12 || tag_end < tag_start) tag_start = tag_end = Length; int length = (int)(tag_end - tag_start); // If the tag isn't at the end of the file, // try appending using padding to improve // write time now or for subsequent writes. if (tag_end != Length) { int padding_size = length - data.Count - 8; if (padding_size < 0) padding_size = 1024; data.Add ("JUNK"); data.Add (ByteVector.FromUInt ( (uint)padding_size, false)); data.Add (new ByteVector (padding_size)); } // Insert the tagging data. Insert (data, tag_start, length); // If the data size changed, and the tagging // data is within the RIFF portion of the file, // update the riff size. if (data.Count - length != 0 && tag_start <= riff_size) Insert (ByteVector.FromUInt ((uint) (riff_size + data.Count - length), false), 4, 4); // Update the tag types. TagTypesOnDisk = TagTypes; } finally { Mode = AccessMode.Closed; } }
public ByteVector Render() { ByteVector vector = new ByteVector(); foreach (TagLib.Tag tag in this.Tags) { if (tag is TagLib.Ape.Tag) { vector.Add((tag as TagLib.Ape.Tag).Render()); } else if (tag is TagLib.Id3v2.Tag) { vector.Add((tag as TagLib.Id3v2.Tag).Render()); } else if (tag is TagLib.Id3v1.Tag) { vector.Add((tag as TagLib.Id3v1.Tag).Render()); } } return vector; }
/// <summary> /// Finds the previous marker of a specified type, starting /// at a specified position. /// </summary> /// <param name="position"> /// A <see cref="long" /> value reference specifying the /// position at which to start searching. This value /// is updated to the position of the found marker. /// </param> /// <param name="marker"> /// A <see cref="Marker" /> value specifying the type of /// marker to search for. /// </param> /// <returns> /// A <see cref="Marker" /> value containing the type of /// marker found at the specified position. This value will /// be identical to <paramref name="marker" />. /// </returns> /// <exception cref="CorruptFileException"> /// A valid marker could not be found. /// </exception> protected Marker RFindMarker (ref long position, Marker marker) { ByteVector packet = new ByteVector (MarkerStart); packet.Add ((byte) marker); position = RFind (packet, position); if (position < 0) throw new CorruptFileException ( "Marker not found"); return GetMarker (position); }
/// <summary> /// Saves the changes made in the current instance to the /// file it represents. /// </summary> public override void Save() { Mode = AccessMode.Write; try { long end; List <Page> pages = new List <Page> (); Dictionary <uint, Bitstream> streams = ReadStreams(pages, out end); Dictionary <uint, Paginator> paginators = new Dictionary <uint, Paginator> (); List <List <Page> > new_pages = new List <List <Page> > (); Dictionary <uint, int> shifts = new Dictionary <uint, int> (); foreach (Page page in pages) { uint id = page.Header.StreamSerialNumber; if (!paginators.ContainsKey(id)) { paginators.Add(id, new Paginator( streams [id].Codec)); } paginators [id].AddPage(page); } foreach (uint id in paginators.Keys) { paginators [id].SetComment( tag.GetComment(id)); int shift; new_pages.Add(new List <Page> ( paginators [id] .Paginate(out shift))); shifts.Add(id, shift); } ByteVector output = new ByteVector(); bool empty; do { empty = true; foreach (List <Page> stream_pages in new_pages) { if (stream_pages.Count == 0) { continue; } output.Add(stream_pages [0].Render()); stream_pages.RemoveAt(0); if (stream_pages.Count != 0) { empty = false; } } } while (!empty); Insert(output, 0, end); InvariantStartPosition = output.Count; InvariantEndPosition = Length; TagTypesOnDisk = TagTypes; Page.OverwriteSequenceNumbers(this, output.Count, shifts); } finally { Mode = AccessMode.Closed; } }