diff options
Diffstat (limited to 'XMPFiles/source/PluginHandler/HostAPIImpl.cpp')
-rw-r--r-- | XMPFiles/source/PluginHandler/HostAPIImpl.cpp | 637 |
1 files changed, 637 insertions, 0 deletions
diff --git a/XMPFiles/source/PluginHandler/HostAPIImpl.cpp b/XMPFiles/source/PluginHandler/HostAPIImpl.cpp new file mode 100644 index 0000000..04dcdd0 --- /dev/null +++ b/XMPFiles/source/PluginHandler/HostAPIImpl.cpp @@ -0,0 +1,637 @@ +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2011 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + +#include "HostAPI.h" +#include "PluginManager.h" +#include "FileHandlerInstance.h" +#include "source/XIO.hpp" +#include "XMPFiles/source/HandlerRegistry.h" + +using namespace Common; + +namespace XMP_PLUGIN +{ + +/////////////////////////////////////////////////////////////////////////////// +// +// Exception handler +// + +static void HandleException( WXMP_Error* wError ) +{ + try + { + throw; + } + catch( XMP_Error& xmpErr ) + { + wError->mErrorMsg = xmpErr.GetErrMsg(); + wError->mErrorID = xmpErr.GetID(); + } + catch( std::exception& stdErr ) + { + wError->mErrorMsg = stdErr.what(); + } + catch( ... ) + { + wError->mErrorMsg = "Caught unknown exception"; + } +} + +/////////////////////////////////////////////////////////////////////////////// +// +// FileIO_API +// + +static XMPErrorID FileSysRead( XMP_IORef io, void* buffer, XMP_Uns32 count, bool readAll, XMP_Uns32& byteRead, WXMP_Error * wError ) +{ + if( wError == NULL ) return kXMPErr_BadParam; + + wError->mErrorID = kXMPErr_InternalFailure; + + try + { + if( io != NULL ) + { + ::XMP_IO * thiz = (::XMP_IO*)io; + byteRead = thiz->Read( buffer, count, readAll ); + wError->mErrorID = kXMPErr_NoError; + } + } + catch( ... ) + { + HandleException( wError ); + } + + return wError->mErrorID; +} + +static XMPErrorID FileSysWrite( XMP_IORef io, void* buffer, XMP_Uns32 count, WXMP_Error * wError ) +{ + if( wError == NULL ) return kXMPErr_BadParam; + + wError->mErrorID = kXMPErr_InternalFailure; + + try + { + if( io != NULL ) + { + ::XMP_IO * thiz = (::XMP_IO*)io; + thiz->Write( buffer, count ); + wError->mErrorID = kXMPErr_NoError; + } + } + catch( ... ) + { + HandleException( wError ); + } + + return wError->mErrorID; +} + +static XMPErrorID FileSysSeek( XMP_IORef io, XMP_Int64& offset, SeekMode mode, WXMP_Error * wError ) +{ + if( wError == NULL ) return kXMPErr_BadParam; + + wError->mErrorID = kXMPErr_InternalFailure; + + try + { + if( io != NULL ) + { + ::XMP_IO * thiz = (::XMP_IO*)io; + thiz->Seek( offset, mode ); + wError->mErrorID = kXMPErr_NoError; + } + } + catch( ... ) + { + HandleException( wError ); + } + + return wError->mErrorID; +} + +static XMPErrorID FileSysLength( XMP_IORef io, XMP_Int64& length, WXMP_Error * wError ) +{ + if( wError == NULL ) return kXMPErr_BadParam; + + wError->mErrorID = kXMPErr_InternalFailure; + + try + { + if( io != NULL ) + { + ::XMP_IO * thiz = (::XMP_IO*)io; + length = thiz->Length(); + wError->mErrorID = kXMPErr_NoError; + } + } + catch( ... ) + { + HandleException( wError ); + } + + return wError->mErrorID; +} + +static XMPErrorID FileSysTruncate( XMP_IORef io, XMP_Int64 length, WXMP_Error * wError ) +{ + if( wError == NULL ) return kXMPErr_BadParam; + + wError->mErrorID = kXMPErr_InternalFailure; + + try + { + if( io != NULL ) + { + ::XMP_IO * thiz = (::XMP_IO*)io; + thiz->Truncate( length ); + wError->mErrorID = kXMPErr_NoError; + } + } + catch( ... ) + { + HandleException( wError ); + } + + return wError->mErrorID; +} + +static XMPErrorID FileSysDeriveTemp( XMP_IORef io, XMP_IORef& tempIO, WXMP_Error * wError ) +{ + if( wError == NULL ) return kXMPErr_BadParam; + + wError->mErrorID = kXMPErr_InternalFailure; + + try + { + if( io != NULL ) + { + ::XMP_IO * thiz = (::XMP_IO*)io; + tempIO = thiz->DeriveTemp(); + wError->mErrorID = kXMPErr_NoError; + } + } + catch( ... ) + { + HandleException( wError ); + } + + return wError->mErrorID; +} + +static XMPErrorID FileSysAbsorbTemp( XMP_IORef io, WXMP_Error * wError ) +{ + if( wError == NULL ) return kXMPErr_BadParam; + + wError->mErrorID = kXMPErr_InternalFailure; + + try + { + if( io != NULL ) + { + ::XMP_IO * thiz = (::XMP_IO*)io; + thiz->AbsorbTemp(); + wError->mErrorID = kXMPErr_NoError; + } + } + catch( ... ) + { + HandleException( wError ); + } + + return wError->mErrorID; +} + +static XMPErrorID FileSysDeleteTemp( XMP_IORef io, WXMP_Error * wError ) +{ + if( wError == NULL ) return kXMPErr_BadParam; + + wError->mErrorID = kXMPErr_InternalFailure; + + try + { + if( io != NULL ) + { + ::XMP_IO * thiz = (::XMP_IO*)io; + thiz->DeleteTemp(); + wError->mErrorID = kXMPErr_NoError; + } + } + catch( ... ) + { + HandleException( wError ); + } + + return wError->mErrorID; +} + +static void GetFileSysAPI( FileIO_API* fileSys ) +{ + if( fileSys ) + { + fileSys->mReadProc = FileSysRead; + fileSys->mWriteProc = FileSysWrite; + fileSys->mSeekProc = FileSysSeek; + fileSys->mLengthProc = FileSysLength; + fileSys->mTruncateProc = FileSysTruncate; + fileSys->mDeriveTempProc = FileSysDeriveTemp; + fileSys->mAbsorbTempProc = FileSysAbsorbTemp; + fileSys->mDeleteTempProc = FileSysDeleteTemp; + } +} + +/////////////////////////////////////////////////////////////////////////////// +// +// String_API +// + +static XMPErrorID CreateBuffer( StringPtr* buffer, XMP_Uns32 size, WXMP_Error * wError ) +{ + if( wError == NULL ) return kXMPErr_BadParam; + + wError->mErrorID = kXMPErr_InternalFailure; + + try + { + if( buffer != NULL ) + { + *buffer = (StringPtr) malloc( size ); + if( *buffer != NULL ) + { + wError->mErrorID = kXMPErr_NoError; + } + else + { + wError->mErrorMsg = "Allocation failed"; + } + } + } + catch( ... ) + { + HandleException( wError ); + } + + return wError->mErrorID; +} + +static XMPErrorID ReleaseBuffer( StringPtr buffer, WXMP_Error * wError ) +{ + if( wError == NULL ) return kXMPErr_BadParam; + + wError->mErrorID = kXMPErr_InternalFailure; + + try + { + if( buffer ) + { + free( buffer ); + wError->mErrorID = kXMPErr_NoError; + } + } + catch( ... ) + { + HandleException( wError ); + } + + return wError->mErrorID; +} + +static void GetStringAPI( String_API* strAPI ) +{ + if( strAPI ) + { + strAPI->mCreateBufferProc = CreateBuffer; + strAPI->mReleaseBufferProc = ReleaseBuffer; + } +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Abort_API +// + +static XMPErrorID CheckAbort( SessionRef session, bool* aborted, WXMP_Error* wError ) +{ + if( wError == NULL ) return kXMPErr_BadParam; + + wError->mErrorID = kXMPErr_InternalFailure; + + if( aborted ) + { + *aborted = false; + + // + // find FileHandlerInstance associated to session reference + // + FileHandlerInstancePtr instance = PluginManager::getHandlerInstance( session ); + + if( instance != NULL ) + { + // + // execute abort procedure if available + // + wError->mErrorID = kXMPErr_NoError; + XMP_AbortProc proc = instance->parent->abortProc; + void* arg = instance->parent->abortArg; + + if( proc ) + { + try + { + *aborted = proc( arg ); + } + catch( ... ) + { + HandleException( wError ); + } + } + } + } + else + { + wError->mErrorMsg = "Invalid parameter"; + } + + return wError->mErrorID; +} + +static void GetAbortAPI( Abort_API* abortAPI ) +{ + if( abortAPI ) + { + abortAPI->mCheckAbort = CheckAbort; + } +} + +/////////////////////////////////////////////////////////////////////////////// +// +// StandardHandler_API +// + +static XMPErrorID CheckFormatStandardHandler( SessionRef session, XMP_FileFormat format, StringPtr path, bool& checkOK, WXMP_Error* wError ) +{ + if( wError == NULL ) return kXMPErr_BadParam; + + wError->mErrorID = kXMPErr_InternalFailure; + wError->mErrorMsg = NULL; + checkOK = false; + + // + // find FileHandlerInstance associated to session reference + // + FileHandlerInstancePtr instance = PluginManager::getHandlerInstance( session ); + + if( instance != NULL && PluginManager::getHandlerPriority( instance ) == PluginManager::kReplacementHandler ) + { + // + // find previous file handler for file format identifier + // + XMPFileHandlerInfo* hdlInfo = HandlerRegistry::getInstance().getStandardHandlerInfo( format ); + + if( hdlInfo != NULL && HandlerRegistry::getInstance().isReplaced( format ) ) + { + if( hdlInfo->checkProc != NULL ) + { + try + { + // + // setup temporary XMPFiles instance + // + XMPFiles standardClient; + standardClient.format = format; + standardClient.filePath = std::string( path ); + + if( hdlInfo->flags & kXMPFiles_FolderBasedFormat ) + { + // + // process folder based handler + // + if( path != NULL ) + { + // The following code corresponds to the one found in HandlerRegistry::selectSmartHandler, + // in the folder based handler selection section of the function + // In this case the format is already known, therefor no folder checks are needed here, + // but the path must be split into the meaningful parts to call checkFolderFormat correctly + + std::string rootPath = path; + std::string leafName; + std::string fileExt; + std::string gpName; + std::string parentName; + + XIO::SplitLeafName ( &rootPath, &leafName ); + + if( !leafName.empty() ) + { + size_t extPos = leafName.size(); + + for ( --extPos; extPos > 0; --extPos ) if ( leafName[extPos] == '.' ) break; + + if( leafName[extPos] == '.' ) + { + fileExt.assign( &leafName[extPos+1] ); + MakeLowerCase( &fileExt ); + leafName.erase( extPos ); + } + + CheckFolderFormatProc CheckProc = (CheckFolderFormatProc) (hdlInfo->checkProc); + + // The case that a logical path to a clip has been passed, which does not point to a real file + if( Host_IO::GetFileMode( path ) == Host_IO::kFMode_DoesNotExist ) + { + checkOK = CheckProc( hdlInfo->format, rootPath, gpName, parentName, leafName, &standardClient ); + } + else + { + XIO::SplitLeafName( &rootPath, &parentName ); + XIO::SplitLeafName( &rootPath, &gpName ); + std::string origGPName ( gpName ); // ! Save the original case for XDCAM-FAM. + MakeUpperCase( &parentName ); + MakeUpperCase( &gpName ); + + if( format == kXMP_XDCAM_FAMFile && ( (parentName == "CLIP") || (parentName == "EDIT") || (parentName == "SUB") ) ) + { + // ! The standard says Clip/Edit/Sub, but we just shifted to upper case. + gpName = origGPName; // ! XDCAM-FAM has just 1 level of inner folder, preserve the "MyMovie" case. + } + + checkOK = CheckProc( hdlInfo->format, rootPath, gpName, parentName, leafName, &standardClient ); + } + } + else + { + wError->mErrorID = kXMPErr_BadParam; + } + } + else + { + wError->mErrorID = kXMPErr_BadParam; + } + } + else + { + // + // file based handler (requires XMP_IO object) + // + CheckFileFormatProc CheckProc = (CheckFileFormatProc) (hdlInfo->checkProc); + XMPFiles_IO* io = XMPFiles_IO::New_XMPFiles_IO ( path, true ); + checkOK = CheckProc( hdlInfo->format, path, io, &standardClient ); + delete io; + } + + wError->mErrorID = kXMPErr_NoError; + } + catch( ... ) + { + HandleException( wError ); + } + } + } + else + { + wError->mErrorMsg = "No standard handler available"; + } + } + else + { + wError->mErrorMsg = "Standard file handler can't call prior handler"; + } + + return wError->mErrorID; +} + +static XMPErrorID GetXMPStandardHandler( SessionRef session, XMP_FileFormat format, StringPtr path, XMPMetaRef xmpRef, bool* xmpExists, WXMP_Error* wError ) +{ + if( wError == NULL ) return kXMPErr_BadParam; + + wError->mErrorID = kXMPErr_InternalFailure; + wError->mErrorMsg = NULL; + + // + // find FileHandlerInstance associated to session reference + // + FileHandlerInstancePtr instance = PluginManager::getHandlerInstance( session ); + + if( instance != NULL && PluginManager::getHandlerPriority( instance ) == PluginManager::kReplacementHandler ) + { + // + // find previous file handler for file format identifier + // + XMPFileHandlerInfo* hdlInfo = HandlerRegistry::getInstance().getStandardHandlerInfo( format ); + + if( hdlInfo != NULL && HandlerRegistry::getInstance().isReplaced( format ) ) + { + // + // check format first + // + bool suc = false; + + XMPErrorID errorID = CheckFormatStandardHandler( session, format, path, suc, wError ); + + if( errorID == kXMPErr_NoError && suc ) + { + // + // setup temporary XMPFiles instance + // + XMPFiles standardClient; + standardClient.format = format; + standardClient.filePath = std::string( path ); + + SXMPMeta meta( xmpRef ); + + try + { + // + // open with passed handler info + // + suc = standardClient.OpenFile( *hdlInfo, path, kXMPFiles_OpenForRead ); + + if( suc ) + { + // + // read meta data + // + suc = standardClient.GetXMP( &meta ); + + if( xmpExists != NULL ) *xmpExists = suc; + } + } + catch( ... ) + { + HandleException( wError ); + } + + // + // close and cleanup + // + try + { + standardClient.CloseFile(); + } + catch( ... ) + { + HandleException( wError ); + } + } + else if( errorID == kXMPErr_NoError ) + { + wError->mErrorID = kXMPErr_BadFileFormat; + wError->mErrorMsg = "Standard handler can't process file format"; + } + } + else + { + wError->mErrorID = kXMPErr_NoFileHandler; + wError->mErrorMsg = "No standard handler available"; + } + } + else + { + wError->mErrorMsg = "Standard file handler can't call prior handler"; + } + + return wError->mErrorID; +} + +static void GetStandardHandlerAPI( StandardHandler_API* standardHandlerAPI ) +{ + if( standardHandlerAPI ) + { + standardHandlerAPI->mCheckFormatStandardHandler = CheckFormatStandardHandler; + standardHandlerAPI->mGetXMPStandardHandler = GetXMPStandardHandler; + } +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Init/Term Host APIs +// + +void PluginManager::SetupHostAPI_V1( HostAPIRef hostAPI ) +{ + // Get XMP_IO APIs + hostAPI->mFileIOAPI = new FileIO_API(); + GetFileSysAPI( hostAPI->mFileIOAPI ); + + // Get String APIs + hostAPI->mStrAPI = new String_API(); + GetStringAPI( hostAPI->mStrAPI ); + + // Get Abort API + hostAPI->mAbortAPI = new Abort_API(); + GetAbortAPI( hostAPI->mAbortAPI ); + + // Get standard handler APIs + hostAPI->mStandardHandlerAPI = new StandardHandler_API(); + GetStandardHandlerAPI( hostAPI->mStandardHandlerAPI ); +} + +} //namespace XMP_PLUGIN |