/* -------------------------------------------------------------------------- */ public TFLACFile() { FID3v2 = new TID3v2(); FHeader = new TFlacHeader(); aMetaBlockOther = new ArrayList(); aExtraFields = new ArrayList(); FResetData(true, true); }
/* -------------------------------------------------------------------------- */ // saves metablocks back to the file // always tries to rebuild header so padding exists after comment block and no more than 1 padding block exists private bool RebuildFile( String sFile, MemoryStream VorbisBlock) { FileStream source = null; BinaryReader r = null; FileStream destination = null; BinaryWriter w = null; long iFileAge; int iNewPadding; int iMetaCount; int iExtraPadding; String sTmp; String BufferName = ""; byte[] MetaDataBlockHeader = new byte[4]; TFlacHeader oldHeader = new TFlacHeader(); MemoryStream MetaBlocks = null; bool bRebuild; bool bRearrange; bool result = false; bRearrange = false; iExtraPadding = 0; if ( !File.Exists(sFile) ) return result; try { iFileAge = 0; if ( bTAG_PreserveDate ) iFileAge = File.GetLastWriteTime(sFile).Ticks; // re arrange other metadata in case of // 1. padding block is not aligned after vorbis comment // 2. insufficient padding - rearange upon file rebuild // 3. fragmented padding blocks iMetaCount = aMetaBlockOther.Count; if ( (FPaddingIndex != FVorbisIndex + 1) || (FPadding <= VorbisBlock.Length - FTagSize ) || FPaddingFragments ) { MetaBlocks = new MemoryStream(); for (int i = 0; i < iMetaCount; i++) { ((TMetaData)aMetaBlockOther[ i ]).MetaDataBlockHeader[ 0 ] = (byte)( ((TMetaData)aMetaBlockOther[i]).MetaDataBlockHeader[ 0 ] & 0x7f ); // not last if (META_PADDING == ((TMetaData)aMetaBlockOther[ i ]).MetaDataBlockHeader[ 0 ]) { iExtraPadding += (int)( ((TMetaData)aMetaBlockOther[ i ]).Data.Length + 4 ); // add padding size plus 4 bytes of header block } else { ((TMetaData)aMetaBlockOther[ i ]).Data.Position = 0; MetaBlocks.Write( ((TMetaData)aMetaBlockOther[ i ]).MetaDataBlockHeader,0,4 ); Utils.CopyMemoryStreamFrom(MetaBlocks,((TMetaData)aMetaBlockOther[ i ]).Data, 0); } } MetaBlocks.Position = 0; bRearrange = true; } // set up file if (FPadding <= VorbisBlock.Length - FTagSize ) // no room rebuild the file from scratch { bRebuild = true; BufferName = sFile + "~"; source = new FileStream( sFile, FileMode.Open, FileAccess.Read ); // Set read-only and open old file, and create new r = new BinaryReader(source); destination = new FileStream( BufferName, FileMode.Create, FileAccess.Write); w = new BinaryWriter(destination); oldHeader.StreamMarker = r.ReadChars(4); oldHeader.MetaDataBlockHeader = r.ReadBytes(4); oldHeader.Info = r.ReadBytes(18); oldHeader.MD5Sum = r.ReadBytes(16); oldHeader.MetaDataBlockHeader[0] = (byte)(oldHeader.MetaDataBlockHeader[0] & 0x7f ); //just in case no metadata existed //w.Write( oldHeader, 0, 32 ); w.Write(oldHeader.StreamMarker); w.Write(oldHeader.MetaDataBlockHeader); w.Write(oldHeader.Info); w.Write(oldHeader.MD5Sum); Utils.CopyMemoryStreamFrom(w, MetaBlocks, 0); } else { bRebuild = false; source = null; destination = new FileStream ( sFile, FileMode.Create, FileAccess.Write); // Set write-access and open file w = new BinaryWriter(destination); if (bRearrange) { destination.Seek( 32, SeekOrigin.Begin ); Utils.CopyMemoryStreamFrom(destination, MetaBlocks, 0); } else { destination.Seek( FVCOffset - 4, SeekOrigin.Begin); } } // finally write vorbis block MetaDataBlockHeader[0] = META_VORBIS_COMMENT; MetaDataBlockHeader[1] = (byte)(( VorbisBlock.Length >> 16 ) & 255 ); MetaDataBlockHeader[2] = (byte)(( VorbisBlock.Length >> 8 ) & 255 ); MetaDataBlockHeader[3] = (byte)( VorbisBlock.Length & 255 ); destination.Write( MetaDataBlockHeader,0, 4 ); Utils.CopyMemoryStreamFrom(destination,VorbisBlock,VorbisBlock.Length); // and add padding if (FPaddingLast || bRearrange) { MetaDataBlockHeader[0] = META_PADDING | 0x80; } else { MetaDataBlockHeader[0] = META_PADDING; } if (bRebuild) { iNewPadding = 4096; // why not... } else { if (FTagSize > VorbisBlock.Length ) { // tag got smaller increase padding iNewPadding = (int)(FPadding + FTagSize - VorbisBlock.Length) + iExtraPadding; } else { // tag got bigger shrink padding iNewPadding = (int)(FPadding - VorbisBlock.Length + FTagSize ) + iExtraPadding; } } MetaDataBlockHeader[1] = (byte)(( iNewPadding >> 16 ) & 255 ); MetaDataBlockHeader[2] = (byte)(( iNewPadding >> 8 ) & 255 ); MetaDataBlockHeader[3] = (byte)( iNewPadding & 255 ); w.Write(MetaDataBlockHeader,0,4); if ((FPadding != iNewPadding) | bRearrange ) { // fill the block with zeros sTmp = ""; for (int i=0; i<iNewPadding; i++) sTmp += '\0'; w.Write( sTmp ); } // finish if ( bRebuild ) { // time to put back the audio data... source.Seek( FAudioOffset, SeekOrigin.Begin ); Utils.CopyMemoryStreamFrom(destination, source, source.Length - FAudioOffset); source.Close(); destination.Close(); //Replace old file and delete temporary file File.Delete( sFile ); File.Copy( BufferName, sFile ); result = true; } else { result = true; destination.Close(); } // post save tasks DateTime newDateTime = new DateTime(iFileAge); if (bTAG_PreserveDate) File.SetLastWriteTime( sFile, newDateTime ); if (bRearrange) MetaBlocks.Close(); } catch (Exception e) { // Access error if ( File.Exists( BufferName ) ) File.Delete( BufferName ); //LogDelegator.GetLogDelegate()(Log.LV_ERROR,e.Message); System.Console.WriteLine(e.StackTrace); } // stream deallocation if (destination != null) destination.Close(); if (source != null) source.Close(); return result; }
/* -------------------------------------------------------------------------- */ public TFLACFile() { FID3v2 = new TID3v2(); FHeader = new TFlacHeader(); aMetaBlockOther = new ArrayList(); aExtraFields = new ArrayList(); FResetData( true, true ); }
/* -------------------------------------------------------------------------- */ // saves metablocks back to the file // always tries to rebuild header so padding exists after comment block and no more than 1 padding block exists private bool RebuildFile(String sFile, MemoryStream VorbisBlock) { FileStream source = null; BinaryReader r = null; FileStream destination = null; BinaryWriter w = null; long iFileAge; int iNewPadding; int iMetaCount; int iExtraPadding; String sTmp; String BufferName = ""; byte[] MetaDataBlockHeader = new byte[4]; TFlacHeader oldHeader = new TFlacHeader(); MemoryStream MetaBlocks = null; bool bRebuild; bool bRearrange; bool result = false; bRearrange = false; iExtraPadding = 0; if (!File.Exists(sFile)) { return(result); } try { iFileAge = 0; if (bTAG_PreserveDate) { iFileAge = File.GetLastWriteTime(sFile).Ticks; } // re arrange other metadata in case of // 1. padding block is not aligned after vorbis comment // 2. insufficient padding - rearange upon file rebuild // 3. fragmented padding blocks iMetaCount = aMetaBlockOther.Count; if ((FPaddingIndex != FVorbisIndex + 1) || (FPadding <= VorbisBlock.Length - FTagSize) || FPaddingFragments) { MetaBlocks = new MemoryStream(); for (int i = 0; i < iMetaCount; i++) { ((TMetaData)aMetaBlockOther[i]).MetaDataBlockHeader[0] = (byte)(((TMetaData)aMetaBlockOther[i]).MetaDataBlockHeader[0] & 0x7f); // not last if (META_PADDING == ((TMetaData)aMetaBlockOther[i]).MetaDataBlockHeader[0]) { iExtraPadding += (int)(((TMetaData)aMetaBlockOther[i]).Data.Length + 4); // add padding size plus 4 bytes of header block } else { ((TMetaData)aMetaBlockOther[i]).Data.Position = 0; MetaBlocks.Write(((TMetaData)aMetaBlockOther[i]).MetaDataBlockHeader, 0, 4); Utils.CopyMemoryStreamFrom(MetaBlocks, ((TMetaData)aMetaBlockOther[i]).Data, 0); } } MetaBlocks.Position = 0; bRearrange = true; } // set up file if (FPadding <= VorbisBlock.Length - FTagSize) // no room rebuild the file from scratch { bRebuild = true; BufferName = sFile + "~"; source = new FileStream(sFile, FileMode.Open, FileAccess.Read); // Set read-only and open old file, and create new r = new BinaryReader(source); destination = new FileStream(BufferName, FileMode.Create, FileAccess.Write); w = new BinaryWriter(destination); oldHeader.StreamMarker = r.ReadChars(4); oldHeader.MetaDataBlockHeader = r.ReadBytes(4); oldHeader.Info = r.ReadBytes(18); oldHeader.MD5Sum = r.ReadBytes(16); oldHeader.MetaDataBlockHeader[0] = (byte)(oldHeader.MetaDataBlockHeader[0] & 0x7f); //just in case no metadata existed //w.Write( oldHeader, 0, 32 ); w.Write(oldHeader.StreamMarker); w.Write(oldHeader.MetaDataBlockHeader); w.Write(oldHeader.Info); w.Write(oldHeader.MD5Sum); Utils.CopyMemoryStreamFrom(w, MetaBlocks, 0); } else { bRebuild = false; source = null; destination = new FileStream(sFile, FileMode.Create, FileAccess.Write); // Set write-access and open file w = new BinaryWriter(destination); if (bRearrange) { destination.Seek(32, SeekOrigin.Begin); Utils.CopyMemoryStreamFrom(destination, MetaBlocks, 0); } else { destination.Seek(FVCOffset - 4, SeekOrigin.Begin); } } // finally write vorbis block MetaDataBlockHeader[0] = META_VORBIS_COMMENT; MetaDataBlockHeader[1] = (byte)((VorbisBlock.Length >> 16) & 255); MetaDataBlockHeader[2] = (byte)((VorbisBlock.Length >> 8) & 255); MetaDataBlockHeader[3] = (byte)(VorbisBlock.Length & 255); destination.Write(MetaDataBlockHeader, 0, 4); Utils.CopyMemoryStreamFrom(destination, VorbisBlock, VorbisBlock.Length); // and add padding if (FPaddingLast || bRearrange) { MetaDataBlockHeader[0] = META_PADDING | 0x80; } else { MetaDataBlockHeader[0] = META_PADDING; } if (bRebuild) { iNewPadding = 4096; // why not... } else { if (FTagSize > VorbisBlock.Length) { // tag got smaller increase padding iNewPadding = (int)(FPadding + FTagSize - VorbisBlock.Length) + iExtraPadding; } else { // tag got bigger shrink padding iNewPadding = (int)(FPadding - VorbisBlock.Length + FTagSize) + iExtraPadding; } } MetaDataBlockHeader[1] = (byte)((iNewPadding >> 16) & 255); MetaDataBlockHeader[2] = (byte)((iNewPadding >> 8) & 255); MetaDataBlockHeader[3] = (byte)(iNewPadding & 255); w.Write(MetaDataBlockHeader, 0, 4); if ((FPadding != iNewPadding) | bRearrange) { // fill the block with zeros sTmp = ""; for (int i = 0; i < iNewPadding; i++) { sTmp += '\0'; } w.Write(sTmp); } // finish if (bRebuild) { // time to put back the audio data... source.Seek(FAudioOffset, SeekOrigin.Begin); Utils.CopyMemoryStreamFrom(destination, source, source.Length - FAudioOffset); source.Close(); destination.Close(); //Replace old file and delete temporary file File.Delete(sFile); File.Copy(BufferName, sFile); result = true; } else { result = true; destination.Close(); } // post save tasks DateTime newDateTime = new DateTime(iFileAge); if (bTAG_PreserveDate) { File.SetLastWriteTime(sFile, newDateTime); } if (bRearrange) { MetaBlocks.Close(); } } catch (Exception e) { // Access error if (File.Exists(BufferName)) { File.Delete(BufferName); } //LogDelegator.GetLogDelegate()(Log.LV_ERROR,e.Message); System.Console.WriteLine(e.StackTrace); } // stream deallocation if (destination != null) { destination.Close(); } if (source != null) { source.Close(); } return(result); }