bool xmp_delete_property(XmpPtr xmp, const char *schema, const char *name) { CHECK_PTR(xmp, false); RESET_ERROR; bool ret = true; SXMPMeta *txmp = (SXMPMeta *)xmp; try { txmp->DeleteProperty(schema, name); } catch(const XMP_Error & e) { set_error(e); ret = false; } catch(...) { ret = false; } return ret; }
// add bwf-bext related data to bext chunk, create if not existing yet. // * in fact, since bext is fully fixed and known, there can be no unknown subchunks worth keeping: // * prepare bext chunk in buffer // * value changed/created if needed only, otherways remove chunk // * remove bext-mapped properties from xmp (non-redundant storage) // note: ValueChunk**: adress of pointer to allow changing the pointer itself (i.e. chunk creation) static void exportXMPtoBextChunk( RIFF_MetaHandler* handler, ValueChunk** bextChunk ) { // register bext namespace ( if there was no import, this is news, otherwise harmless moot) SXMPMeta::RegisterNamespace( kXMP_NS_BWF, "bext:", 0 ); bool chunkUsed = false; // assume for now SXMPMeta* xmp = &handler->xmpObj; // prepare buffer, need to know CodingHistory size as the only variable XMP_Int32 bextBufferSize = MIN_BEXT_SIZE - 8; // -8 because of header std::string value; if ( xmp->GetProperty( bextCodingHistory.ns, bextCodingHistory.prop, &value, kXMP_NoOptions )) { bextBufferSize += ((XMP_StringLen)value.size()) + 1 ; // add to size (and a trailing zero) } // create and clear buffer XMP_Uns8* buffer = new XMP_Uns8[bextBufferSize]; for (XMP_Int32 i = 0; i < bextBufferSize; i++ ) buffer[i] = 0; // grab props, write into buffer, remove from XMP /////////////////////////// // bextDescription ------------------------------------------------ if ( xmp->GetProperty( bextDescription.ns, bextDescription.prop, &value, kXMP_NoOptions ) ) { setBextField( &value, (XMP_Uns8*) buffer, 0, 256 ); xmp->DeleteProperty( bextDescription.ns, bextDescription.prop) ; chunkUsed = true; } // bextOriginator ------------------------------------------------- if ( xmp->GetProperty( bextOriginator.ns , bextOriginator.prop, &value, kXMP_NoOptions ) ) { setBextField( &value, (XMP_Uns8*) buffer, 256, 32 ); xmp->DeleteProperty( bextOriginator.ns , bextOriginator.prop ); chunkUsed = true; } // bextOriginatorRef ---------------------------------------------- if ( xmp->GetProperty( bextOriginatorRef.ns , bextOriginatorRef.prop, &value, kXMP_NoOptions ) ) { setBextField( &value, (XMP_Uns8*) buffer, 256+32, 32 ); xmp->DeleteProperty( bextOriginatorRef.ns , bextOriginatorRef.prop ); chunkUsed = true; } // bextOriginationDate -------------------------------------------- if ( xmp->GetProperty( bextOriginationDate.ns , bextOriginationDate.prop, &value, kXMP_NoOptions ) ) { setBextField( &value, (XMP_Uns8*) buffer, 256+32+32, 10 ); xmp->DeleteProperty( bextOriginationDate.ns , bextOriginationDate.prop ); chunkUsed = true; } // bextOriginationTime -------------------------------------------- if ( xmp->GetProperty( bextOriginationTime.ns , bextOriginationTime.prop, &value, kXMP_NoOptions ) ) { setBextField( &value, (XMP_Uns8*) buffer, 256+32+32+10, 8 ); xmp->DeleteProperty( bextOriginationTime.ns , bextOriginationTime.prop ); chunkUsed = true; } // bextTimeReference ---------------------------------------------- // thanx to friendly byte order, all 8 bytes can be written in one go: if ( xmp->GetProperty( bextTimeReference.ns, bextTimeReference.prop, &value, kXMP_NoOptions ) ) { try { XMP_Int64 v = SXMPUtils::ConvertToInt64( value.c_str() ); PutUns64LE( v, &(buffer[256+32+32+10+8] )); chunkUsed = true; } catch (XMP_Error& e) { if ( e.GetID() != kXMPErr_BadParam ) throw e; // re-throw on any other error } // 'else' tolerate ( time reference remains 0x00000000 ) // valid or not, do not store redundantly: xmp->DeleteProperty( bextTimeReference.ns, bextTimeReference.prop ); } // bextVersion ---------------------------------------------------- // set version=1, no matter what. PutUns16LE( 1, &(buffer[256+32+32+10+8+8]) ); xmp->DeleteProperty( bextVersion.ns, bextVersion.prop ); // bextUMID ------------------------------------------------------- if ( xmp->GetProperty( bextUMID.ns, bextUMID.prop, &value, kXMP_NoOptions ) ) { std::string rawStr; if ( !DecodeFromHexString( value.data(), (XMP_StringLen) value.size(), &rawStr ) ) { delete [] buffer; // important. XMP_Throw ( "EncodeFromHexString: illegal umid string. Must contain an even number of 0-9 and uppercase A-F chars.", kXMPErr_BadParam ); } // if UMID is smaller/longer than 64 byte for any reason, // truncate/do a partial write (just like for any other bext property) memcpy( (char*) &(buffer[256+32+32+10+8+8+2]), rawStr.data(), MIN( 64, rawStr.size() ) ); xmp->DeleteProperty( bextUMID.ns, bextUMID.prop ); chunkUsed = true; } // bextCodingHistory ---------------------------------------------- if ( xmp->GetProperty( bextCodingHistory.ns, bextCodingHistory.prop, &value, kXMP_NoOptions ) ) { std::string ascii; convertToASCII( value.data(), (XMP_StringLen) value.size() , &ascii, (XMP_StringLen) value.size() ); strncpy( (char*) &(buffer[MIN_BEXT_SIZE-8]), ascii.data(), ascii.size() ); xmp->DeleteProperty( bextCodingHistory.ns, bextCodingHistory.prop ); chunkUsed = true; } // always delete old, recreate if needed if ( *bextChunk != 0 ) { (*bextChunk)->parent->replaceChildWithJunk( *bextChunk ); (*bextChunk) = 0; // clear direct Chunk pointer } if ( chunkUsed) *bextChunk = new ValueChunk( handler->riffChunks.at(0), std::string( (char*)buffer, bextBufferSize ), kChunk_bext ); delete [] buffer; // important. }