//******************************************************************************************************
// RiffChunk.cs - Gbtc
//
// Copyright © 2012, Grid Protection Alliance. All Rights Reserved.
//
// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
// the NOTICE file distributed with this work for additional information regarding copyright ownership.
// The GPA licenses this file to you under the MIT License (MIT), the "License"; you may
// not use this file except in compliance with the License. You may obtain a copy of the License at:
//
// http://www.opensource.org/licenses/MIT
//
// Unless agreed to in writing, the subject software distributed under the License is distributed on an
// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
// License for the specific language governing permissions and limitations.
//
// Code Modification History:
// ----------------------------------------------------------------------------------------------------
// 07/29/2009 - J. Ritchie Carroll
// Generated original version of source code.
// 09/14/2009 - Stephen C. Wills
// Added new header and license agreement.
// 12/14/2012 - Starlynn Danyelle Gilliam
// Modified Header.
//
//******************************************************************************************************
#region [ Contributor License Agreements ]
/**************************************************************************\
Copyright © 2009 - J. Ritchie Carroll
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\**************************************************************************/
#endregion
using System;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Text;
using GSF.Parsing;
namespace GSF.Media
{
///
/// Represents the type ID and size for a "chunk" in a RIFF media format file.
///
///
///
/// The Resource Interchange File Format (RIFF) is a generic meta-format for storing data in tagged chunks.
/// It was introduced in 1991 by Microsoft and IBM, and was presented by Microsoft as the default format for
/// Windows 3.1 multimedia files. It is based on Electronic Arts's Interchange File Format, introduced in 1985,
/// the only difference being that multi-byte integers are in little-endian format, native to the 80x86 processor
/// series used in IBM PCs, rather than the big-endian format native to the 68k processor series used in Amiga and
/// Apple Macintosh computers, where IFF files were heavily used. (The specification for AIFF, the big-endian
/// analogue of RIFF, was published by Apple Computer in 1988.) The Microsoft implementation is mostly known
/// through file formats like AVI, ANI and WAV, which use the RIFF meta-format as their basis.
///
///
/// Some common RIFF file types:
///
///
/// File extension
/// Description
///
/// -
/// WAV
/// Windows audio file
///
/// -
/// AVI
/// Windows audio/video file
///
/// -
/// ANI
/// Animated Windows cursors
///
/// -
/// RMI
/// Windows RIFF MIDI file
///
/// -
/// CDR
/// CorelDRAW vector graphics file
///
///
///
///
public class RiffChunk : ISupportBinaryImage
{
#region [ Members ]
// Constants
///
/// The fixed byte length of a instance.
///
public const int FixedLength = 8;
// Fields
private string m_typeID;
private int m_chunkSize;
#endregion
#region [ Constructors ]
private RiffChunk()
{
}
///
/// Constructor for derived classes used to initialize and validate properties.
///
/// Pre-parsed header.
/// Expected type ID.
protected RiffChunk(RiffChunk preRead, string typeID)
{
if (typeID != preRead.TypeID)
throw new InvalidDataException(string.Format("{0} chunk expected but got {1}, file does not appear to be valid", typeID, preRead.TypeID));
m_typeID = preRead.TypeID;
m_chunkSize = preRead.ChunkSize;
}
///
/// Constructs a new for the given .
///
/// Expected type ID.
public RiffChunk(string typeID)
{
m_typeID = typeID;
}
#endregion
#region [ Properties ]
/// Four character text identifer for RIFF chunk.
/// TypeID cannot be null.
/// TypeID must be extactly 4 characters in length.
public string TypeID
{
get
{
return m_typeID;
}
set
{
if ((object)value == null)
throw new ArgumentNullException(nameof(value));
if (value.Length != 4)
throw new ArgumentOutOfRangeException(nameof(value), "TypeID must be exactly 4 characters in length");
m_typeID = value;
}
}
/// Size of .
public virtual int ChunkSize
{
get
{
return m_chunkSize;
}
set
{
m_chunkSize = value;
}
}
///
/// Gets the length of a consisting of type ID and chunk size (i.e., 8 bytes).
///
public virtual int BinaryLength
{
get
{
return FixedLength;
}
}
#endregion
#region [ Methods ]
///
/// Generates a binary representation of this and copies it into the given buffer.
///
/// Buffer used to hold generated binary image of the source object.
/// 0-based starting index in the to start writing.
/// The number of bytes written to the .
/// is null.
///
/// or is less than 0 -or-
/// and will exceed length.
///
public virtual int GenerateBinaryImage(byte[] buffer, int startIndex)
{
buffer.ValidateParameters(startIndex, FixedLength);
Buffer.BlockCopy(Encoding.ASCII.GetBytes(TypeID), 0, buffer, 0, 4);
Buffer.BlockCopy(LittleEndian.GetBytes(ChunkSize), 0, buffer, 4, 4);
return FixedLength;
}
// This is not currently needed since the RIFF chunks are read using the static ReadNext
[SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes")]
int ISupportBinaryImage.ParseBinaryImage(byte[] buffer, int startIndex, int length)
{
throw new NotImplementedException();
}
///
/// Creates a copy of the .
///
/// A new copy of the .
public RiffChunk Clone()
{
RiffChunk riffChunk = new RiffChunk(m_typeID);
riffChunk.ChunkSize = m_chunkSize;
return riffChunk;
}
#endregion
#region [ Static ]
// Static Methods
///
/// Attempts to read the next RIFF chunk from the stream.
///
/// Source stream for next RIFF chunk.
/// Next RIFF chunk read from the stream.
/// RIFF chunk too small, media file corrupted.
public static RiffChunk ReadNext(Stream source)
{
RiffChunk riffChunk = new RiffChunk();
int length = riffChunk.BinaryLength;
byte[] buffer = new byte[length];
int bytesRead = source.Read(buffer, 0, length);
if (bytesRead < length)
throw new InvalidOperationException("RIFF chunk too small, media file corrupted");
riffChunk.TypeID = Encoding.ASCII.GetString(buffer, 0, 4);
riffChunk.ChunkSize = LittleEndian.ToInt32(buffer, 4);
return riffChunk;
}
#endregion
}
}