/// /// Reads a subset of the id3 information /// public ID3v2( string path, bool verboseDump ) { _debugDump = verboseDump; _stream = new FileStream( path, FileMode.Open, FileAccess.Read, FileShare.Read ); _reader = new Mp3StreamReader( _stream ); try { // Find the start of the ID3v2 tag in our stream: _header = _FindHeader( false ); Debug.Assert( null != _header ); if (_debugDump) { _Trace( " isValid: " + _header.isValid ); _Trace( " version: " + _header.version ); _Trace( " flags: " + _header.flags ); _Trace( " isUnsynchronized: " + _header.isUnsynchronized ); _Trace( " hasExtendedHeader: " + _header.hasExtendedHeader ); _Trace( " isExperimental: " + _header.isExperimental ); _Trace( " hasFooter: " + _header.hasFooter ); _Trace( " size: " + _header.size ); } if (_header.isUnsynchronized) { throw new ApplicationException( "Sorry, whole-tag unsynchronization not yet implemented" ); } // For now, forget about it _SkipExtendedHeader(); // skip to the meat // Finally, start looking for interesting information in the // stream. _ReadFrames(); } catch (ID3TagNotFoundException nfe) { _header = null; // not found. Boo! } finally { _reader = null; _stream.Close(); _stream = null; } }
/// /// \param tryTheEnd - if false, we only look in the first 3 bytes /// for a header. /// ID3v2Header _FindHeader( bool tryTheEnd ) { // look for the tag at the start or end of the file. If it's // somewhere in the middle, forget it. /// \bug We should be ready to deal with id3 tags in the middle /// of the file, but this isn't very likely, so... // From the FAQ: // # Q: Where is an ID3v2 tag located in an MP3 file? // It is most likely located at the beginning of the file. // // Look for the marker "ID3" in the first 3 bytes of the file. // // If it's not there, it could be at the end of the file // (if the tag is ID3v2.4). Look for the marker "3DI" 10 // bytes from the end of the file, or 10 bytes before the // beginning of an ID3v1 tag. // // Finally it is possible to embed ID3v2 tags in the actual // MPEG stream, on an MPEG frame boundry. Almost nobody does // this. // // Try the start byte [] buffer = new byte[10]; _reader.Read( buffer, 10 ); // get the file header ID3v2Header header = new ID3v2Header( buffer, true ); if (header.isValid) { if (_debugDump) _Trace( " Found header at start" ); return header; } if (!tryTheEnd) { /// \todo search for id3v2 tag in the middle of the file /// throw new ID3TagNotFoundException(); } // Seek to end of file (new for 2.4) _Trace( "FIXME: look for ID3v2.4 tag at EOF" ); throw new ID3TagNotFoundException(); }