void WAVE_MetaHandler::ProcessXMP()
{
	// Must be done only once
	if ( this->processedXMP ) 
	{
		return;
	}
	// Set the status at start, in case something goes wrong in this method
	this->processedXMP = true;

	// Parse the XMP
	if ( ! this->xmpPacket.empty() ) {
	
		XMP_Assert ( this->containsXMP );
		
		FillPacketInfo ( this->xmpPacket, &this->packetInfo );

		this->xmpObj.ParseFromBuffer ( this->xmpPacket.c_str(), (XMP_StringLen)this->xmpPacket.size() );

		this->containsXMP = true;
	}

	// Then import native properties
	MetadataSet metaSet;
	WAVEReconcile recon;

	// Parse the WAVE metadata object with values

	const XMP_Uns8* buffer = NULL; // temporary buffer
	XMP_Uns64 size = 0;
	// Get LIST:INFO legacy chunk
	mINFOChunk = mChunkController->getChunk( mWAVEInfoChunkPath, true );
	if( mINFOChunk != NULL )
	{			
		size = mINFOChunk->getData( &buffer );
		mINFOMeta.parse( buffer, size );
	}

	// Parse Bext legacy chunk
	mBEXTChunk = mChunkController->getChunk( mWAVEBextChunkPath, true );
	if( mBEXTChunk != NULL )
	{	
		size = mBEXTChunk->getData( &buffer );
		mBEXTMeta.parse( buffer, size );
	 }

	// Parse cart legacy chunk
	mCartChunk = mChunkController->getChunk( mWAVECartChunkPath, true );
	if( mCartChunk != NULL )
	{	
		size = mCartChunk->getData( &buffer );
		mCartMeta.parse( buffer, size );
	 }

	// Parse DISP legacy chunk
	const std::vector<IChunkData*>& disps = mChunkController->getChunks( mWAVEDispChunkPath );

	if( ! disps.empty() )
	{
		for( std::vector<IChunkData*>::const_reverse_iterator iter=disps.rbegin(); iter!=disps.rend(); iter++ )
		{
			size = (*iter)->getData( &buffer );
			
			if( DISPMetadata::isValidDISP( buffer, size ) )
			{
				mDISPChunk = (*iter);
				break;
			}
		}
	}

	if( mDISPChunk != NULL )
	{	
		size = mDISPChunk->getData( &buffer );
		mDISPMeta.parse( buffer, size );
	}
	
	//cr8r is not yet required for WAVE
	//// Parse Cr8r legacy chunk
	//mCr8rChunk = mChunkController->getChunk( mWAVECr8rChunkPath );
	//if( mCr8rChunk != NULL )
	//{	
	//	size = mCr8rChunk->getData( &buffer );
	//	mCr8rMeta.parse( buffer, size );
	//}
	
	// app legacy to the metadata list
	metaSet.append( &mINFOMeta );
	metaSet.append( &mBEXTMeta );
	metaSet.append( &mCartMeta );
	metaSet.append( &mDISPMeta );

	// cr8r is not yet required for WAVE
	// metaSet.append( &mCr8rMeta );
	
	// Do the import
	if( recon.importToXMP( this->xmpObj, metaSet ) )
	{
		// Remember if anything has changed
		this->containsXMP = true;
	}
	
} // WAVE_MetaHandler::ProcessXMP
void WAVE_MetaHandler::UpdateFile ( bool doSafeUpdate )
{
	if ( ! this->needsUpdate ) {	// If needsUpdate is set then at least the XMP changed.
		return;
	}

	if ( doSafeUpdate )
	{
		XMP_Throw ( "WAVE_MetaHandler::UpdateFile: Safe update not supported", kXMPErr_Unavailable );
	}

	// Export XMP to legacy chunks. Create/delete them if necessary
	MetadataSet metaSet;
	WAVEReconcile recon;
	
	metaSet.append( &mINFOMeta );
	metaSet.append( &mBEXTMeta );
	metaSet.append( &mCartMeta );
	metaSet.append( &mDISPMeta );

	// cr8r is not yet required for WAVE
	// metaSet.append( &mCr8rMeta );

	// If anything changes, update/create/delete the legacy chunks
	if( recon.exportFromXMP( metaSet, this->xmpObj ) )
	{		
		if ( mINFOMeta.hasChanged( ))
		{
			updateLegacyChunk( &mINFOChunk, kChunk_LIST, kType_INFO, mINFOMeta );
		}

		if ( mBEXTMeta.hasChanged( ))
		{
			updateLegacyChunk( &mBEXTChunk, kChunk_bext, kType_NONE, mBEXTMeta );
		}

		if ( mCartMeta.hasChanged( ))
		{
			updateLegacyChunk( &mCartChunk, kChunk_cart, kType_NONE, mCartMeta );
		}

		if ( mDISPMeta.hasChanged( ))
		{
			updateLegacyChunk( &mDISPChunk, kChunk_DISP, kType_NONE, mDISPMeta );
		}

		//cr8r is not yet required for WAVE
		//if ( mCr8rMeta.hasChanged( ))
		//{
		//	updateLegacyChunk( &mCr8rChunk, kChunk_Cr8r, kType_NONE, mCr8rMeta );
		//}
	}

	//update/create XMP chunk
	if( this->containsXMP )
	{
		this->xmpObj.SerializeToBuffer ( &(this->xmpPacket) );

		if( mXMPChunk != NULL )
		{
			mXMPChunk->setData( reinterpret_cast<const XMP_Uns8 *>(this->xmpPacket.c_str()), this->xmpPacket.length() );
		}
		else // create XMP chunk
		{
			mXMPChunk = mChunkController->createChunk( kChunk_XMP, kType_NONE );
			mXMPChunk->setData( reinterpret_cast<const XMP_Uns8 *>(this->xmpPacket.c_str()), this->xmpPacket.length() );
			mChunkController->insertChunk( mXMPChunk );
		}
	}
	// XMP Packet is never completely removed from the file.
	
	XMP_ProgressTracker* progressTracker=this->parent->progressTracker;
	// local progess tracking required because  for Handlers incapable of 
	// kXMPFiles_CanRewrite XMPFiles call this Update method after making
	// a copy of the orignal file
	bool localProgressTracking=false;
	if ( progressTracker != 0 )
	{
		if ( ! progressTracker->WorkInProgress() ) 
		{
			localProgressTracking = true;
			progressTracker->BeginWork ();
		}
	}
	//write tree back to file
	mChunkController->writeFile( this->parent->ioRef ,progressTracker);
	if ( localProgressTracking && progressTracker != 0 ) progressTracker->WorkComplete();

	this->needsUpdate = false;	// Make sure this is only called once.
}	// WAVE_MetaHandler::UpdateFile
void WAVE_MetaHandler::UpdateFile ( bool doSafeUpdate )
{
	if ( ! this->needsUpdate ) {	// If needsUpdate is set then at least the XMP changed.
		return;
	}

	if ( doSafeUpdate )
	{
		XMP_Throw ( "WAVE_MetaHandler::UpdateFile: Safe update not supported", kXMPErr_Unavailable );
	}

	// Export XMP to legacy chunks. Create/delete them if necessary
	MetadataSet metaSet;
	WAVEReconcile recon;
	
	metaSet.append( &mINFOMeta );
	metaSet.append( &mBEXTMeta );
	metaSet.append( &mCartMeta );
	metaSet.append( &mDISPMeta );

	// cr8r is not yet required for WAVE
	// metaSet.append( &mCr8rMeta );

	// If anything changes, update/create/delete the legacy chunks
	if( recon.exportFromXMP( metaSet, this->xmpObj ) )
	{		
		if ( mINFOMeta.hasChanged( ))
		{
			updateLegacyChunk( &mINFOChunk, kChunk_LIST, kType_INFO, mINFOMeta );
		}

		if ( mBEXTMeta.hasChanged( ))
		{
			updateLegacyChunk( &mBEXTChunk, kChunk_bext, kType_NONE, mBEXTMeta );
		}

		if ( mCartMeta.hasChanged( ))
		{
			updateLegacyChunk( &mCartChunk, kChunk_cart, kType_NONE, mCartMeta );
		}

		if ( mDISPMeta.hasChanged( ))
		{
			updateLegacyChunk( &mDISPChunk, kChunk_DISP, kType_NONE, mDISPMeta );
		}

		//cr8r is not yet required for WAVE
		//if ( mCr8rMeta.hasChanged( ))
		//{
		//	updateLegacyChunk( &mCr8rChunk, kChunk_Cr8r, kType_NONE, mCr8rMeta );
		//}
	}

	//update/create XMP chunk
	if( this->containsXMP )
	{
		this->xmpObj.SerializeToBuffer ( &(this->xmpPacket) );

		if( mXMPChunk != NULL )
		{
			mXMPChunk->setData( reinterpret_cast<const XMP_Uns8 *>(this->xmpPacket.c_str()), this->xmpPacket.length() );
		}
		else // create XMP chunk
		{
			mXMPChunk = mChunkController->createChunk( kChunk_XMP, kType_NONE );
			mXMPChunk->setData( reinterpret_cast<const XMP_Uns8 *>(this->xmpPacket.c_str()), this->xmpPacket.length() );
			mChunkController->insertChunk( mXMPChunk );
		}
	}
	// XMP Packet is never completely removed from the file.

	//write tree back to file
	mChunkController->writeFile( this->parent->ioRef );

	this->needsUpdate = false;	// Make sure this is only called once.
}	// WAVE_MetaHandler::UpdateFile