Esempio n. 1
0
void P2_MetaHandler::UpdateFile ( bool doSafeUpdate )
{
	if ( ! this->needsUpdate ) return;
	this->needsUpdate = false;	// Make sure only called once.

	XMP_Assert ( this->parent->UsesLocalIO() );

	// Update the internal legacy XML tree if we have one, and set the digest in the XMP.

	bool updateLegacyXML = false;
	P2_Clip* p2Clip = 0;
	XML_NodePtr clipMetadata = 0;
	if ( this->p2ClipManager.IsValidP2() )
	{
		p2Clip=this->p2ClipManager.GetManagedClip();
		clipMetadata = p2Clip->GetClipMetadataNode();
		if ( clipMetadata != 0 ) {

			bool xmpFound;
			std::string xmpValue;
			XML_Node * xmlNode;

			xmpFound = this->xmpObj.GetLocalizedText ( kXMP_NS_DC, "title", "", "x-default", 0, &xmpValue, 0 );

			if ( xmpFound && p2Clip->GetClipContentNode()) {

				xmlNode = this->ForceChildElement ( p2Clip->GetClipContentNode(), "ClipName", 3, false );

				if ( xmpValue != xmlNode->GetLeafContentValue() ) {
					xmlNode->SetLeafContentValue ( xmpValue.c_str() );
					updateLegacyXML = true;
				}

			}

			xmpFound = this->xmpObj.GetArrayItem ( kXMP_NS_DC, "creator", 1, &xmpValue, 0 );

			if ( xmpFound ) {
				xmlNode = this->ForceChildElement ( clipMetadata , "Access", 3, false );

				// "Creator" must be first child of "Access" node else Panasonic P2 Viewer gives an error.
				xmlNode = this->ForceChildElement ( xmlNode, "Creator", 4 , true);
				if ( xmpValue != xmlNode->GetLeafContentValue() ) {
					xmlNode->SetLeafContentValue ( xmpValue.c_str() );
					updateLegacyXML = true;
				}
			}
		}

		// Half the startTimeCode frame number value in XML if require so
		std::string xmpStartTimeCode;
		bool isTimecodeExists = this->xmpObj.GetStructField(kXMP_NS_DM, "startTimecode", kXMP_NS_DM, "timeValue", &xmpStartTimeCode, 0);
		if (isTimecodeExists)
		{
			std::string frameFormat;
			this->xmpObj.GetStructField(kXMP_NS_DM, "startTimecode", kXMP_NS_DM, "timeFormat", &frameFormat, 0);
			if (frameFormat == "50Timecode" || frameFormat == "5994DropTimecode" || frameFormat == "5994NonDropTimecode")
			{
				p2Clip = this->p2ClipManager.GetManagedClip();
				XMP_StringPtr p2NS = p2Clip->GetP2RootNode()->ns.c_str();
				XML_NodePtr legacyVideoContext = p2Clip->GetEssenceListNode();
				if (legacyVideoContext != 0)
				{
					legacyVideoContext = legacyVideoContext->GetNamedElement(p2NS, "Video");
					XML_NodePtr legacyProp = legacyVideoContext->GetNamedElement(p2NS, "StartTimecode");
					if ((legacyProp != 0) && legacyProp->IsLeafContentNode())
					{
						AdjustTimeCode( xmpStartTimeCode, true );
						if (xmpStartTimeCode != legacyProp->GetLeafContentValue())
						{
							legacyProp->SetLeafContentValue(xmpStartTimeCode.c_str());
							updateLegacyXML = true;
						}
					}
				}
			}
		}

		std::string newDigest;
		this->p2ClipManager.GetManagedClip()->CreateDigest ( &newDigest );
		this->xmpObj.SetStructField ( kXMP_NS_XMP, "NativeDigests", kXMP_NS_XMP, "P2", newDigest.c_str(), kXMP_DeleteExisting );
	}

	this->xmpObj.SerializeToBuffer ( &this->xmpPacket, this->GetSerializeOptions() );

	// -----------------------------------------------------------------------
	// Update the XMP file first, don't let legacy XML failures block the XMP.

	std::string xmpPath;
	this->MakeClipFilePath ( &xmpPath, ".XMP" );

	bool haveXMP = Host_IO::Exists ( xmpPath.c_str() );
	if ( ! haveXMP ) {
		XMP_Assert ( this->parent->ioRef == 0 );
		Host_IO::Create ( xmpPath.c_str() );
		this->parent->ioRef = XMPFiles_IO::New_XMPFiles_IO ( xmpPath.c_str(), Host_IO::openReadWrite );
		if ( this->parent->ioRef == 0 ) XMP_Throw ( "Failure opening P2 XMP file", kXMPErr_ExternalFailure );
	}

	XMP_IO* xmpFile = this->parent->ioRef;
	XMP_Assert ( xmpFile != 0 );
	XIO::ReplaceTextFile ( xmpFile, this->xmpPacket, (haveXMP & doSafeUpdate) );

	// --------------------------------------------
	// Now update the legacy XML file if necessary.

	if ( updateLegacyXML ) {

		std::string legacyXML, xmlPath;

		/*bug # 3217688: xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance namespace must be defined at the 
		root node "P2Main" in legacy XML else Panasonic P2 Viewer gives an error. So we are adding a 
		dummy attribute with this namespace to clipContent/clipMetadata (whichever is non-null) before
		serializing the XML tree. We are also undoing it below after serialization.*/

		XML_Node *parentNode = AddXSINamespace(p2Clip->GetClipContentNode(), clipMetadata);
		p2Clip->SerializeP2ClipContent ( legacyXML );
		if(parentNode){
			// Remove the dummy attribute added to clipContent/clipMetadata.
			delete parentNode->attrs[parentNode->attrs.size()-1];
			parentNode->attrs.pop_back();
		}

		this->MakeClipFilePath ( &xmlPath, ".XML" );

		bool haveXML = Host_IO::Exists ( xmlPath.c_str() );
		if ( ! haveXML ) Host_IO::Create ( xmlPath.c_str() );

		Host_IO::FileRef hostRef = Host_IO::Open ( xmlPath.c_str(), Host_IO::openReadWrite );
		if ( hostRef == Host_IO::noFileRef ) XMP_Throw ( "Failure opening P2 legacy XML file", kXMPErr_ExternalFailure );
		XMPFiles_IO origXML ( hostRef, xmlPath.c_str(), Host_IO::openReadWrite );
		XIO::ReplaceTextFile ( &origXML, legacyXML, (haveXML & doSafeUpdate) );
		origXML.Close();

	}

}	// P2_MetaHandler::UpdateFile