public static Id3v2Frame CreateFrame(ByteVector data, uint version) { Id3v2FrameHeader header = new Id3v2FrameHeader(data, version); ByteVector frameId = header.FrameId; // A quick sanity check -- make sure that the frameId is 4 uppercase // Latin1 characters. Also make sure that there is data in the frame. if (frameId == null || frameId.Count != (version < 3 ? 3 : 4) || header.FrameSize < 0) { return(null); } foreach (byte b in frameId) { char c = (char)b; if ((c < 'A' || c > 'Z') && (c < '1' || c > '9')) { return(null); } } // Windows Media Player may create zero byte frames. Just send them // off as unknown. if (header.FrameSize == 0) { return(new Id3v2UnknownFrame(data, header)); } // TagLib doesn'type mess with encrypted frames, so just treat them // as unknown frames. if (header.Compression) { TagLibDebugger.Debug("Compressed frames are currently not supported."); return(new Id3v2UnknownFrame(data, header)); } if (header.Encryption) { TagLibDebugger.Debug("Encrypted frames are currently not supported."); return(new Id3v2UnknownFrame(data, header)); } if (!UpdateFrame(header)) { header.TagAlterPreservation = true; return(new Id3v2UnknownFrame(data, header)); } foreach (FrameCreator creator in frameCreators) { Id3v2Frame frame = creator(data, header); if (frame != null) { return(frame); } } // UpdateFrame() might have updated the frame ID. frameId = header.FrameId; // This is where things get necissarily nasty. Here we determine which // Frame subclass (or if none is found simply an Frame) based // on the frame ID. Since there are a lot of possibilities, that means // a lot of if blocks. // Text Identification (frames 4.2) if (frameId.StartsWith("T")) { Id3v2TextIdentificationFrame frame = frameId != "TXXX" ? new Id3v2TextIdentificationFrame(data, header) : new Id3v2UserTextIdentificationFrame(data, header); if (useDefaultEncoding) { frame.TextEncoding = defaultEncoding; } return(frame); } // Comments (frames 4.10) if (frameId == "COMM") { Id3v2CommentsFrame frame = new Id3v2CommentsFrame(data, header); if (useDefaultEncoding) { frame.TextEncoding = defaultEncoding; } return(frame); } // Attached Picture (frames 4.14) if (frameId == "APIC") { Id3v2AttachedPictureFrame f = new Id3v2AttachedPictureFrame(data, header); if (useDefaultEncoding) { f.TextEncoding = defaultEncoding; } return(f); } // Relative Volume Adjustment (frames 4.11) if (frameId == "RVA2") { return(new Id3v2RelativeVolumeFrame(data, header)); } // Unique File Identifier (frames 4.1) if (frameId == "UFID") { return(new Id3v2UniqueFileIdentifierFrame(data, header)); } // Private (frames 4.27) if (frameId == "PRIV") { return(new Id3v2PrivateFrame(data, header)); } return(new Id3v2UnknownFrame(data, header)); }
private void Scan() { // Scan the metadata pages if (scanned || !IsValid) { return; } uint ipacket = 0; long overhead = 0; ByteVector metadata_header = GetPacket(ipacket++); if (metadata_header == null) { return; } ByteVector header; if (!metadata_header.StartsWith("fLaC")) { // FLAC 1.1.2+ if (metadata_header.Mid(1, 4) != "FLAC") { return; } if (metadata_header[5] != 1) { return; // not version 1 } metadata_header = metadata_header.Mid(13); } else { // FLAC 1.1.0 & 1.1.1 metadata_header = GetPacket(ipacket++); if (metadata_header == null) { return; } } header = metadata_header.Mid(0, 4); // Header format (from spec): // <1> Last-metadata-block flag // <7> BLOCK_TYPE // 0 : STREAMINFO // 1 : PADDING // .. // 4 : VORBIS_COMMENT // .. // <24> Length of metadata to follow byte block_type = (byte)(header[0] & 0x7f); bool last_block = (header[0] & 0x80) != 0; uint length = header.Mid(1, 3).ToUInt(); overhead += length; // Sanity: First block should be the stream_info metadata if (block_type != 0) { TagLibDebugger.Debug("Ogg.Flac.File.Scan() -- Invalid Ogg/FLAC stream"); return; } stream_info_data = metadata_header.Mid(4, (int)length); // Search through the remaining metadata while (!last_block) { metadata_header = GetPacket(ipacket++); if (metadata_header == null) { return; } header = metadata_header.Mid(0, 4); block_type = (byte)(header[0] & 0x7f); last_block = (header[0] & 0x80) != 0; length = header.Mid(1, 3).ToUInt(); overhead += length; if (block_type == 4) { xiph_comment_data = metadata_header.Mid(4, (int)length); has_xiph_comment = true; comment_packet = ipacket; } else if (block_type > 5) { TagLibDebugger.Debug("Ogg.Flac.File.Scan() -- Unknown metadata block"); } } // End of metadata, now comes the datastream stream_start = overhead; stream_length = Length - stream_start; scanned = true; }