📄 wav_handler.cpp
字号:
// Writing all the chunks RIFF_Support::WriteChunk ( fileRef, wavInfoCreateDateChunk, strCreateDate.c_str(), GetStringRiffSize ( strCreateDate ) ); RIFF_Support::WriteChunk ( fileRef, wavInfoArtistChunk, strArtist.c_str(), GetStringRiffSize ( strArtist ) ); RIFF_Support::WriteChunk ( fileRef, wavInfoAlbumChunk, strAlbum.c_str(), GetStringRiffSize ( strAlbum ) ); RIFF_Support::WriteChunk ( fileRef, wavInfoGenreChunk, strGenre.c_str(), GetStringRiffSize ( strGenre ) ); RIFF_Support::WriteChunk ( fileRef, wavInfoCommentChunk, strComment.c_str(), GetStringRiffSize ( strComment ) ); RIFF_Support::WriteChunk ( fileRef, wavInfoEngineerChunk, strEngineer.c_str(), GetStringRiffSize ( strEngineer ) ); RIFF_Support::WriteChunk ( fileRef, wavInfoCopyrightChunk, strCopyright.c_str(), GetStringRiffSize ( strCopyright ) ); RIFF_Support::WriteChunk ( fileRef, wavInfoSoftwareChunk, strSoftware.c_str(), GetStringRiffSize ( strSoftware ) ); LFA_Write ( fileRef, strOldInfo.c_str(), lOldSize ); } this->needsUpdate = false;} // WAV_MetaHandler::UpdateFile// =================================================================================================// WAV_MetaHandler::WriteFile// ==========================void WAV_MetaHandler::WriteFile ( LFA_FileRef sourceRef, const std::string & sourcePath ){ IgnoreParam(sourceRef); IgnoreParam(sourcePath); XMP_Throw ( "WAV_MetaHandler::WriteFile: Not supported", kXMPErr_Unavailable );} // WAV_MetaHandler::WriteFile// =================================================================================================static void AddDigestItem ( XMP_Uns32 legacyID, std::string & legacyStr, std::string * digestStr, MD5_CTX * md5 ){ XMP_Uns32 leID = MakeUns32LE ( legacyID ); XMP_Uns32 leLen = MakeUns32LE (legacyStr.size()); digestStr->append ( (char*)(&leID), 4 ); digestStr->append ( "," ); MD5Update ( md5, (XMP_Uns8*)&leID, 4 ); MD5Update ( md5, (XMP_Uns8*)&leLen, 4 ); MD5Update ( md5, (XMP_Uns8*)legacyStr.c_str(), legacyStr.size() );} // AddDigestItem// =================================================================================================static void AddCurrentDigestItem ( LFA_FileRef fileRef, RIFF_Support::RiffState riffState, XMP_Uns32 tagID, XMP_Uns32 parentID, std::string * digestStr, MD5_CTX * md5 ){ unsigned long legacySize; std::string legacyStr; bool found = RIFF_Support::GetRIFFChunk ( fileRef, riffState, tagID, parentID, 0, 0, &legacySize ); if ( found ) { legacyStr.reserve ( legacySize ); legacyStr.assign ( legacySize, ' ' ); (void) RIFF_Support::GetRIFFChunk ( fileRef, riffState, tagID, parentID, 0, (char*)legacyStr.c_str(), &legacySize ); } AddDigestItem ( tagID, legacyStr, digestStr, md5 );} // AddCurrentDigestItem// =================================================================================================static void CreateCurrentDigest ( LFA_FileRef fileRef, RIFF_Support::RiffState riffState, std::string * digestStr ){ MD5_CTX md5Ctx; XMP_Uns8 md5Val[16]; static char* hexDigits = "0123456789ABCDEF"; MD5Init ( &md5Ctx ); AddCurrentDigestItem ( fileRef, riffState, wavWaveTitleChunk, wavWaveTag, digestStr, &md5Ctx ); AddCurrentDigestItem ( fileRef, riffState, wavInfoArtistChunk, wavInfoTag, digestStr, &md5Ctx ); AddCurrentDigestItem ( fileRef, riffState, wavInfoCommentChunk, wavInfoTag, digestStr, &md5Ctx ); AddCurrentDigestItem ( fileRef, riffState, wavInfoCopyrightChunk, wavInfoTag, digestStr, &md5Ctx); AddCurrentDigestItem ( fileRef, riffState, wavInfoCreateDateChunk, wavInfoTag, digestStr, &md5Ctx ); AddCurrentDigestItem ( fileRef, riffState, wavInfoEngineerChunk, wavInfoTag, digestStr, &md5Ctx ); AddCurrentDigestItem ( fileRef, riffState, wavInfoGenreChunk, wavInfoTag, digestStr, &md5Ctx ); AddCurrentDigestItem ( fileRef, riffState, wavInfoAlbumChunk, wavInfoTag, digestStr, &md5Ctx ); AddCurrentDigestItem ( fileRef, riffState, wavInfoSoftwareChunk, wavInfoTag, digestStr, &md5Ctx ); MD5Final ( md5Val, &md5Ctx ); (*digestStr)[digestStr->size()-1] = ';'; for ( size_t i = 0; i < 16; ++i ) { XMP_Uns8 byte = md5Val[i]; (*digestStr) += hexDigits [byte >> 4]; (*digestStr) += hexDigits [byte & 0xF]; }} // CreateCurrentDigest// =================================================================================================// WAV_MetaHandler::CacheFileData// ==============================void WAV_MetaHandler::CacheFileData(){ this->containsXMP = false; bool fReconciliate = ! (this->parent->openFlags & kXMPFiles_OpenOnlyXMP); bool keepExistingXMP = false; // By default an import will replace existing XMP. bool haveLegacyItem, haveXMPItem; LFA_FileRef fileRef ( this->parent->fileRef ); RIFF_Support::RiffState riffState; long numTags = RIFF_Support::OpenRIFF ( fileRef, riffState ); if ( numTags == 0 ) return; // Determine the size of the metadata unsigned long bufferSize(0); haveLegacyItem = RIFF_Support::GetRIFFChunk ( fileRef, riffState, kXMPUserDataType, 0, 0, 0, &bufferSize ); if ( ! haveLegacyItem ) { packetInfo.writeable = true; // If no packet found, created packets will be writeable } else if ( bufferSize > 0 ) { // Size and clear the buffer this->xmpPacket.reserve(bufferSize); this->xmpPacket.assign(bufferSize, ' '); // Get the metadata haveLegacyItem = RIFF_Support::GetRIFFChunk ( fileRef, riffState, kXMPUserDataType, 0, 0, const_cast<char *>(this->xmpPacket.data()), &bufferSize ); if ( haveLegacyItem ) { this->packetInfo.offset = kXMPFiles_UnknownOffset; this->packetInfo.length = bufferSize; this->xmpObj.ParseFromBuffer ( this->xmpPacket.c_str(), this->xmpPacket.size() ); this->containsXMP = true; } } // Figure out what to do overall. If there is no XMP, everything gets imported. If there is XMP // but no digest, only import if there is no corresponding XMP. If there is XMP and a digest // that matches, nothing is imported. If there is XMP and a digest that does not match, import // everything that provides "new info". if ( fReconciliate && this->containsXMP ) { std::string savedDigest; haveXMPItem = this->xmpObj.GetProperty ( kXMP_NS_WAV, "NativeDigest", &savedDigest, 0 ); if ( ! haveXMPItem ) { keepExistingXMP = true; } else { std::string currDigest; CreateCurrentDigest ( fileRef, riffState, &currDigest ); if ( currDigest == savedDigest ) fReconciliate = false; } } // Now import the individual legacy items. if ( fReconciliate ) { ImportLegacyItem ( riffState, wavWaveTitleChunk, wavWaveTag, kXMP_NS_DC, kTitle, keepExistingXMP, true /* LangAlt */ ); ImportLegacyItem ( riffState, wavInfoCreateDateChunk, wavInfoTag, kXMP_NS_XMP, kCreateDate, keepExistingXMP ); ImportLegacyItem ( riffState, wavInfoArtistChunk, wavInfoTag, kXMP_NS_DM, kArtist, keepExistingXMP ); ImportLegacyItem ( riffState, wavInfoAlbumChunk, wavInfoTag, kXMP_NS_DM, kAlbum, keepExistingXMP ); ImportLegacyItem ( riffState, wavInfoGenreChunk, wavInfoTag, kXMP_NS_DM, kGenre, keepExistingXMP ); ImportLegacyItem ( riffState, wavInfoCommentChunk, wavInfoTag, kXMP_NS_DM, kLogComment, keepExistingXMP ); ImportLegacyItem ( riffState, wavInfoEngineerChunk, wavInfoTag, kXMP_NS_DM, kEngineer, keepExistingXMP ); ImportLegacyItem ( riffState, wavInfoCopyrightChunk, wavInfoTag, kXMP_NS_DC, kCopyright, keepExistingXMP, true /* LangAlt */ ); ImportLegacyItem ( riffState, wavInfoSoftwareChunk, wavInfoTag, kXMP_NS_XMP, kSoftware, keepExistingXMP ); } // Update the xmpPacket, as the xmpObj might have been updated with legacy info this->xmpObj.SerializeToBuffer ( &this->xmpPacket, kXMP_UseCompactFormat ); this->packetInfo.offset = kXMPFiles_UnknownOffset; this->packetInfo.length = this->xmpPacket.size(); this->processedXMP = this->containsXMP; } // WAV_MetaHandler::CacheFileData// =================================================================================================void WAV_MetaHandler::UTF8ToMBCS ( std::string * inoutStr ){ std::string localStr; try { ReconcileUtils::UTF8ToLocal ( inoutStr->c_str(), inoutStr->size(), &localStr ); inoutStr->swap ( localStr ); } catch ( ... ) { inoutStr->erase(); }}// =================================================================================================void WAV_MetaHandler::MBCSToUTF8 ( std::string * inoutStr ){ std::string utf8Str; try { ReconcileUtils::LocalToUTF8 ( inoutStr->c_str(), inoutStr->size(), &utf8Str ); inoutStr->swap ( utf8Str ); } catch ( ... ) { inoutStr->erase(); }}// =================================================================================================void WAV_MetaHandler::PrepareLegacyExport ( XMP_StringPtr xmpNS, XMP_StringPtr xmpProp, XMP_Uns32 legacyID, std::string * legacyStr, std::string * digestStr, MD5_CTX * md5, bool langAlt /* = false */ ){ if ( ! langAlt ) { this->xmpObj.GetProperty ( xmpNS, xmpProp, legacyStr, 0 ); } else { this->xmpObj.GetLocalizedText ( xmpNS, xmpProp, "", "x-default", 0, legacyStr, 0 ); } UTF8ToMBCS ( legacyStr ); // Convert the XMP value to local encoding. // ! Add a 0 pad byte if the value has an odd length. This would be better done inside RIFF_Support, // ! but that means changing too much at this moment. if ( (legacyStr->size() & 1) == 1 ) { (*legacyStr) += " "; (*legacyStr)[legacyStr->size()-1] = 0; } if ( legacyID == wavWaveTitleChunk ) { // ! The title gets 32 bit LE type code of 1 inserted. legacyStr->insert ( 0, "1234" ); PutUns32LE ( 1, (void*)legacyStr->c_str() ); } AddDigestItem ( legacyID, *legacyStr, digestStr, md5 );} // WAV_MetaHandler::PrepareLegacyExport// =================================================================================================void WAV_MetaHandler::ImportLegacyItem ( RIFF_Support::RiffState & inOutRiffState, XMP_Uns32 tagID, XMP_Uns32 parentID, XMP_StringPtr xmpNS, XMP_StringPtr xmpProp, bool keepExistingXMP, bool langAlt /* = false */ ){ LFA_FileRef fileRef ( this->parent->fileRef ); bool haveLegacyItem, haveXMPItem; std::string legacyStr, xmpStr; unsigned long legacySize; if ( ! langAlt ) { haveXMPItem = this->xmpObj.GetProperty ( xmpNS, xmpProp, &xmpStr, 0 ); } else { haveXMPItem = this->xmpObj.GetLocalizedText ( xmpNS, xmpProp, "", "x-default", 0, &xmpStr, 0 ); } haveLegacyItem = RIFF_Support::GetRIFFChunk ( fileRef, inOutRiffState, tagID, parentID, 0, 0, &legacySize ); if ( (legacySize == 0) || ((tagID == wavWaveTitleChunk) && (legacySize <= 4)) ) haveLegacyItem = false; if ( haveXMPItem && keepExistingXMP ) haveLegacyItem = false; // Simplify following checks. if ( ! haveLegacyItem ) { // No legacy item, delete the corresponding XMP if we're not keeping existing XMP. if ( haveXMPItem && (! keepExistingXMP) ) { if ( ! langAlt ) { this->xmpObj.DeleteProperty ( xmpNS, xmpProp ); } else { std::string xdPath; SXMPUtils::ComposeLangSelector ( xmpNS, xmpProp, "x-default", &xdPath ); this->xmpObj.DeleteProperty ( xmpNS, xdPath.c_str() ); if ( this->xmpObj.CountArrayItems ( xmpNS, xmpProp ) == 0 ) this->xmpObj.DeleteProperty ( xmpNS, xmpProp ); } } } else { // Have a legacy Item, update the XMP as appropriate. XMP_Assert ( (! haveXMPItem) || (! keepExistingXMP) ); legacyStr.reserve ( legacySize ); legacyStr.assign ( legacySize, ' ' ); haveLegacyItem = RIFF_Support::GetRIFFChunk ( fileRef, inOutRiffState, tagID, parentID, 0, (char*)legacyStr.c_str(), &legacySize ); XMP_Assert ( haveLegacyItem ); if ( tagID == wavWaveTitleChunk ) { // Check and strip the type code from the title. XMP_Assert ( legacySize > 4 ); XMP_Uns32 typeCode = GetUns32LE ( legacyStr.data() ); if( typeCode != 1 ) return; // Bail if the type code isn't 1. legacyStr.erase ( 0, 4 ); // Reduce the value to just the text part. } if ( haveXMPItem ) { // Don't update the XMP if the legacy value matches the localized XMP value. UTF8ToMBCS ( &xmpStr ); if ( xmpStr == legacyStr ) return; } MBCSToUTF8 ( &legacyStr ); if ( ! langAlt ) { this->xmpObj.SetProperty ( xmpNS, xmpProp, legacyStr.c_str(), 0 ); } else { this->xmpObj.SetLocalizedText ( xmpNS, xmpProp, "", "x-default", legacyStr.c_str(), 0 ); } this->containsXMP = true; }} // WAV_MetaHandler::LoadPropertyFromRIFF
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -