1 // =================================================================================================
2 // ADOBE SYSTEMS INCORPORATED
3 // Copyright 2010 Adobe Systems Incorporated
4 // All Rights Reserved
5 //
6 // NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms
7 // of the Adobe license agreement accompanying it.
8 // =================================================================================================
9 
10 #ifndef _WAVEBEHAVIOR_h_
11 #define _WAVEBEHAVIOR_h_
12 
13 #include "public/include/XMP_Environment.h"	// ! XMP_Environment.h must be the first included header.
14 
15 #include "public/include/XMP_Const.h"
16 #include "public/include/XMP_IO.hpp"
17 
18 #include "XMPFiles/source/FormatSupport/IFF/IChunkBehavior.h"
19 #include "XMPFiles/source/FormatSupport/IFF/ChunkPath.h"
20 #include "source/Endian.h"
21 
22 namespace IFF_RIFF
23 {
24 
25 /**
26 	WAVE behavior class.
27 
28 	Implements the IChunkBehavior interface
29 */
30 
31 
32 class WAVEBehavior : public IChunkBehavior
33 {
34 // Internal structure to hold RF64 related data
35 public:
36 #if SUNOS_SPARC || SUNOS_X86
37 #pragma pack ( 1 )
38 #else
39 #pragma pack ( push, 1 )
40 #endif //#if SUNOS_SPARC || SUNOS_X86
41 	struct ChunkSize64
42 	{
43 		XMP_Uns64 size;
44 		XMP_Uns32 id;
45 		// Ctor
ChunkSize64ChunkSize6446 		ChunkSize64(): size(0), id(0) {}
47 	};
48 
49 	struct DS64
50 	{
51 		XMP_Uns64 riffSize;
52 		XMP_Uns64 dataSize;
53 		XMP_Uns64 sampleCount;
54 		XMP_Uns32 tableLength;
55 		// fix part ends here
56 		XMP_Uns32 trailingBytes;
57 		std::vector<ChunkSize64> table;
58 
59 		// ctor
DS64DS6460 		DS64(): riffSize(0), dataSize(0), sampleCount(0), tableLength(0), trailingBytes(0) {}
61 	};
62 #if SUNOS_SPARC || SUNOS_X86
63 #pragma pack (  )
64 #else
65 #pragma pack ( pop )
66 #endif //#if SUNOS_SPARC || SUNOS_X86
67 
68 
69 	/**
70 		ctor/dtor
71 	*/
WAVEBehavior()72 	WAVEBehavior() : mChunksAdded(0), mIsRF64(false), mDS64Data(NULL) {}
73 
~WAVEBehavior()74 	virtual ~WAVEBehavior()
75 	{
76 		if( mDS64Data != NULL )
77 		{
78 			delete mDS64Data;
79 		}
80 	}
81 
82 	/**
83 		Validate the passed in size value, identify the valid size if the passed in isn't valid
84 		and return the valid size.
85 		throw an exception if the passed in size isn't valid and there's no way to identify a
86 		valid size.
87 
88 		@param	size	Size value
89 		@param	id		Identifier of chunk
90 		@param	tree	Chunk tree
91 		@param	stream	Stream handle
92 
93 		@return		Valid size value.
94 	*/
95 	XMP_Uns64		getRealSize( const XMP_Uns64 size, const ChunkIdentifier& id, IChunkContainer& tree, XMP_IO* stream );
96 
97 	/**
98 		Return the maximum size of a single chunk, i.e. the maximum size of a top-level chunk.
99 
100 		@return		Maximum size
101 	*/
102 	XMP_Uns64		getMaxChunkSize() const;
103 
104 	/**
105 		Return true if the passed identifier is valid for top-level chunks of a certain format.
106 
107 		@param	id		Chunk identifier
108 		@param	chunkNo	order number of top-level chunk
109 		@return			true, if passed id is a valid top-level chunk
110 	*/
111 	bool			isValidTopLevelChunk( const ChunkIdentifier& id, XMP_Uns32 chunkNo );
112 
113 	/**
114 		Fix the hierarchy of chunks depending ones based on size changes of one or more chunks
115 		and second based on format specific rules.
116 		Throw an exception if the hierarchy can't be fixed.
117 
118 		@param	tree		Vector of root chunks.
119 	*/
120 	void			fixHierarchy( IChunkContainer& tree );
121 
122 	/**
123 		Insert a new chunk into the hierarchy of chunks. The behavior needs to decide the position
124 		of the new chunk and has to do the insertion.
125 
126 		@param	tree	Chunk tree
127 		@param	chunk	New chunk
128 	*/
129 	void			insertChunk( IChunkContainer& tree, Chunk& chunk )	;
130 
131 	/**
132 		Remove the chunk described by the passed ChunkPath.
133 
134 		@param	tree	Chunk tree
135 		@param	path	Path to the chunk that needs to be removed
136 
137 		@return			true if the chunk was removed and need to be deleted
138 	*/
139 	bool			removeChunk( IChunkContainer& tree, Chunk& chunk )	;
140 
141 protected:
142 		/**
143 		Create a FREE chunk.
144 		If the chunkSize is smaller than the header+type - size then create an annotation chunk.
145 		If the passed size is odd, then add a pad byte.
146 
147 		@param chunkSize	Total size including header
148 		@return				New FREE chunk
149 	*/
150 	Chunk*			createFREE( XMP_Uns64 chunkSize );
151 
152 	/**
153 		Check if the passed chunk is a FREE chunk.
154 		(Could be also a small annotation chunk with zero bytes in its data)
155 
156 		@param	chunk	A chunk
157 
158 		@return			true if the passed chunk is a FREE chunk
159 	*/
160 	XMP_Bool		isFREEChunk( const Chunk& chunk ) const;
161 
162 	/**
163 		Return the minimum size of a FREE chunk
164 	*/
165 	XMP_Uns64		getMinFREESize( ) const;
166 
167 	/**
168 		Is the current file a RF64 file?
169 
170 		@param tree		The whole chunk tree beginning with the root node
171 
172 		@return			true if the current file is in the RF64 format
173 	*/
174 	bool			isRF64( const IChunkContainer& tree );
175 
176 	/**
177 		Return RF64 structure.
178 
179 		If the related chunk ('ds64') is not yet parsed then it should be parsed by this method.
180 
181 		@param tree		The chunk tree (probably a subtree)
182 		@param stream	File stream
183 
184 		@return			DS64 structure
185 	*/
186 	DS64*			getDS64( IChunkContainer& tree, XMP_IO* stream );
187 
188 	/**
189 		update the RF64 chunk (if this is RF64) based on the current chunk sizes
190 	*/
191 	void			updateRF64( IChunkContainer& tree );
192 
193 	/**
194 	 * Parses the data block of the given RF64 chunk into the internal data structures
195 	 * @param rf64Chunk the RF64 Chunk
196 	 * @param rf64 OUT the RF64 data structure
197 	 * @return The parsing was successful (true) or not (false)
198 	 */
199 	bool			parseDS64Chunk( const Chunk& ds64Chunk, DS64& rf64 );
200 
201 	/**
202 	 * Serializes the internal RF64 data structures into the data part of the given chunk
203 	 * @param rf64 the RF64 data structure
204 	 * @param rf64Chunk OUT the RF64 Chunk
205 	 * @return The serialization was successful (true) or not (false)
206 	 */
207 	bool			serializeDS64Chunk( const WAVEBehavior::DS64& rf64, Chunk& ds64Chunk );
208 
209 private:
210 	void			doUpdateRF64( Chunk& chunk );
211 
212 private:
213 	XMP_Uns32	mChunksAdded;
214 	bool		mIsRF64;
215 	DS64*		mDS64Data;
216 
217 	static const LittleEndian& mEndian;				// WAVE is always Little Endian
218 	static const XMP_Uns32 kNormalRF64ChunkSize = 0xFFFFFFFF;
219 	static const XMP_Uns32 kMinimumDS64ChunkSize = 28;
220 }; // IFF_RIFF
221 
222 }
223 #endif
224