////////////////////////////////////////////////////////////////////////// // public members ////////////////////////////////////////////////////////////////////////// public static Frame CreateFrame(ByteVector data, ref int offset, byte version) { int position = offset; FrameHeader header = new FrameHeader(data.Mid(position, (int)FrameHeader.Size(version)), version); offset += (int)(header.FrameSize + FrameHeader.Size(version)); if (header.FrameId == null) { throw new System.NotImplementedException(); } foreach (byte b in header.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 and delete them. if (header.FrameSize == 0) { header.Flags |= FrameFlags.TagAlterPreservation; return(new UnknownFrame(data, position, header, version)); } // TODO: Support Compression. if ((header.Flags & FrameFlags.Compression) != 0) { throw new System.NotImplementedException(); } // TODO: Support Encryption. if ((header.Flags & FrameFlags.Encryption) != 0) { throw new System.NotImplementedException(); } foreach (FrameCreator creator in frame_creators) { Frame frame = creator(data, position, header, version); if (frame != null) { return(frame); } } // 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 (header.FrameId == FrameType.TXXX) { return(new UserTextInformationFrame(data, position, header, version)); } if (header.FrameId [0] == (byte)'T') { return(new TextInformationFrame(data, position, header, version)); } // Unique File Identifier (frames 4.1) if (header.FrameId == FrameType.UFID) { return(new UniqueFileIdentifierFrame(data, position, header, version)); } // Music CD Identifier (frames 4.5) if (header.FrameId == FrameType.MCDI) { return(new MusicCdIdentifierFrame(data, position, header, version)); } // Unsynchronized Lyrics (frames 4.8) if (header.FrameId == FrameType.USLT) { return(new UnsynchronisedLyricsFrame(data, position, header, version)); } // Synchronized Lyrics (frames 4.9) if (header.FrameId == FrameType.SYLT) { return(new SynchronisedLyricsFrame(data, position, header, version)); } // Comments (frames 4.10) if (header.FrameId == FrameType.COMM) { return(new CommentsFrame(data, position, header, version)); } // Relative Volume Adjustment (frames 4.11) if (header.FrameId == FrameType.RVA2) { return(new RelativeVolumeFrame(data, position, header, version)); } // Attached Picture (frames 4.14) if (header.FrameId == FrameType.APIC) { return(new AttachedPictureFrame(data, position, header, version)); } // General Encapsulated Object (frames 4.15) if (header.FrameId == FrameType.GEOB) { return(new GeneralEncapsulatedObjectFrame(data, position, header, version)); } // Play Count (frames 4.16) if (header.FrameId == FrameType.PCNT) { return(new PlayCountFrame(data, position, header, version)); } // Play Count (frames 4.17) if (header.FrameId == FrameType.POPM) { return(new PopularimeterFrame(data, position, header, version)); } // Terms of Use (frames 4.22) if (header.FrameId == FrameType.USER) { return(new TermsOfUseFrame(data, position, header, version)); } // Private (frames 4.27) if (header.FrameId == FrameType.PRIV) { return(new PrivateFrame(data, position, header, version)); } return(new UnknownFrame(data, position, header, version)); }
protected ByteVector FieldData(ByteVector frameData, int offset, byte version) { if (frameData == null) { throw new ArgumentNullException("frameData"); } int data_offset = offset + (int)FrameHeader.Size(version); int data_length = (int)Size; /*int uncompressed_data_length;*/ if ((Flags & (FrameFlags.Compression | FrameFlags.DataLengthIndicator)) != 0) { /*uncompressed_data_length = (int) frame_data.Mid (data_offset, 4).ToUInt () + 4;*/ data_offset += 4; data_offset -= 4; } if ((Flags & FrameFlags.GroupingIdentity) != 0) { group_id = frameData [data_offset++]; data_length--; } if ((Flags & FrameFlags.Encryption) != 0) { encryption_id = frameData [data_offset++]; data_length--; } if (data_length > frameData.Count - data_offset) { throw new CorruptFileException("Frame size exceeds bounds."); } if (data_length < 0) { throw new CorruptFileException("Frame size less than zero."); } ByteVector data = frameData.Mid(data_offset, data_length); if ((Flags & FrameFlags.Unsychronisation) != 0) { SynchData.ResynchByteVector(data); } // FIXME: Implement encryption. if ((Flags & FrameFlags.Encryption) != 0) { throw new NotImplementedException(); } // FIXME: Implement compression. if ((Flags & FrameFlags.Compression) != 0) { throw new NotImplementedException(); } /* * if(d->header->compression()) { * ByteVector data(frameDataLength); * uLongf uLongTmp = frameDataLength; * ::uncompress((Bytef *) data.data(), * (uLongf *) &uLongTmp, * (Bytef *) frameData.data() + frameDataOffset, * size()); * return data; * } */ return(data); }