void HTMLClipTest::OpenHTMLClip() { assert(_pHeader); HRESULT hr = S_OK; aafNumSlots_t compositionMobs = 0; IEnumAAFMobs *pEnumMobs = NULL; IAAFMob *pReferencingMob = NULL; IAAFCompositionMob *pCompositionMob = NULL; aafNumSlots_t mobSlots = 0; IEnumAAFMobSlots *pEnumSlots = NULL; IAAFMobSlot *pMobSlot = NULL; IAAFSegment *pSegment = NULL; IAAFHTMLClip *pHTMLClip = NULL; aafUInt32 bufSize = 0; aafUInt32 actualBufSize = 0; aafUInt32 actualLength = 0; wchar_t *pBeginAnchor = NULL; wchar_t *pEndAnchor = NULL; IAAFSourceReference *pSourceReference = NULL; aafMobID_t masterMobID = {0}; IAAFMasterMob *pMasterMob = NULL; IAAFMob *pReferencedMob = NULL; try { // Get the number of composition mobs in the file (should be one) checkResult(_pHeader->CountMobs(kAAFCompMob, &compositionMobs)); checkExpression(1 == compositionMobs, AAFRESULT_TEST_FAILED); // Get the composition mob. There should only be one. aafSearchCrit_t criteria; criteria.searchTag = kAAFByMobKind; criteria.tags.mobKind = kAAFCompMob; checkResult(_pHeader->GetMobs(&criteria, &pEnumMobs)); checkResult(pEnumMobs->NextOne(&pReferencingMob)); checkResult(pReferencingMob->QueryInterface(IID_IAAFCompositionMob, (void **)&pCompositionMob)); // Get the html clip in the slot. There should be only one. checkResult(pReferencingMob->CountSlots(&mobSlots)); checkExpression(1 == mobSlots, AAFRESULT_TEST_FAILED); checkResult(pReferencingMob->GetSlots(&pEnumSlots)); checkResult(pEnumSlots->NextOne(&pMobSlot)); checkResult(pMobSlot->GetSegment(&pSegment)); checkResult(pSegment->QueryInterface(IID_IAAFHTMLClip, (void **)&pHTMLClip)); // Validate the properties... checkResult(pHTMLClip->GetBeginAnchorBufLen(&bufSize)); actualLength = wcslen(_beginAnchor) + 1; actualBufSize = actualLength * 2; checkExpression(bufSize == actualBufSize, AAFRESULT_TEST_FAILED); pBeginAnchor = new wchar_t[actualLength]; checkExpression(NULL != pBeginAnchor, AAFRESULT_NOMEMORY); checkResult(pHTMLClip->GetBeginAnchor(pBeginAnchor, actualBufSize)); checkExpression(0 == wcscmp(pBeginAnchor, _beginAnchor), AAFRESULT_TEST_FAILED); checkResult(pHTMLClip->GetEndAnchorBufLen(&bufSize)); actualLength = wcslen(_endAnchor) + 1; actualBufSize = actualLength * 2; checkExpression(bufSize == actualBufSize, AAFRESULT_TEST_FAILED); pEndAnchor = new wchar_t[actualLength]; checkExpression(NULL != pEndAnchor, AAFRESULT_NOMEMORY); checkResult(pHTMLClip->GetEndAnchor(pEndAnchor, actualBufSize)); checkExpression(0 == wcscmp(pEndAnchor, _endAnchor), AAFRESULT_TEST_FAILED); // Attempt to "resolve" the reference and find the master mob. checkResult(pHTMLClip->QueryInterface(IID_IAAFSourceReference, (void **)&pSourceReference)); checkResult(pSourceReference->GetSourceID(&masterMobID)); checkExpression(0 == memcmp(&masterMobID, &_referencedMobID, sizeof(masterMobID)), AAFRESULT_TEST_FAILED); checkResult(_pHeader->LookupMob(masterMobID, &pReferencedMob)); checkResult(pReferencedMob->QueryInterface(IID_IAAFMasterMob, (void **)&pMasterMob)); // Use EssenceAccess to read some html essence // Find the file mob for the html essence. // Find the corresponding html essence. // Read some html essence. } catch (HRESULT& rHR) { hr = rHR; // fall through and handle cleanup } // Cleanup local references if (pMasterMob) { pMasterMob->Release(); pMasterMob = NULL; } if (pReferencedMob) { pReferencedMob->Release(); pReferencedMob = NULL; } if (pSourceReference) { pSourceReference->Release(); pSourceReference = NULL; } if (pEndAnchor) { delete [] pEndAnchor; pEndAnchor = NULL; } if (pBeginAnchor) { delete [] pBeginAnchor; pBeginAnchor = NULL; } if (pHTMLClip) { pHTMLClip->Release(); pHTMLClip = NULL; } if (pSegment) { pSegment->Release(); pSegment = NULL; } if (pMobSlot) { pMobSlot->Release(); pMobSlot = NULL; } if (pEnumSlots) { pEnumSlots->Release(); pEnumSlots = NULL; } if (pCompositionMob) { pCompositionMob->Release(); pCompositionMob = NULL; } if (pReferencingMob) { pReferencingMob->Release(); pReferencingMob = NULL; } if (pEnumMobs) { pEnumMobs->Release(); pEnumMobs = NULL; } // Propogate the error if necessary. checkResult(hr); }
void EventTest::OpenEvent() { assert(_pHeader); HRESULT hr = S_OK; IAAFMob *pMob = NULL; IEnumAAFMobSlots *pEnumSlots = NULL; IAAFMobSlot *pMobSlot = NULL; IAAFEventMobSlot *pEventMobSlot = NULL; aafRational_t editRate = {0}; IAAFSegment *pSegment = NULL; IAAFEvent *pEvent = NULL; aafPosition_t position; wchar_t eventComment[128]; try { // Get the composition mob that we created to hold the checkResult(_pHeader->LookupMob(gMobID, &pMob)); // Get the first mob slot and check that it is an event mob slot. checkResult(pMob->GetSlots(&pEnumSlots)); checkResult(pEnumSlots->NextOne(&pMobSlot)); checkResult(pMobSlot->QueryInterface(IID_IAAFEventMobSlot, (void **)&pEventMobSlot)); checkResult(pEventMobSlot->GetEditRate(&editRate)); checkExpression(0 == memcmp(&editRate, &_editRate, sizeof(editRate)), AAFRESULT_TEST_FAILED); // Get the event slot's segment and check that it is an event. checkResult(pMobSlot->GetSegment(&pSegment)); checkResult(pSegment->QueryInterface(IID_IAAFEvent, (void **)&pEvent)); // Now validate the event property values we thought were written to the // file. // Validate the position checkResult(pEvent->GetPosition(&position)); checkExpression(0 == memcmp(&position, &_position, sizeof(position)), AAFRESULT_TEST_FAILED); // Validate the comment buffer size. aafUInt32 expectedLen = wcslen(_eventComment) + 1; aafUInt32 expectedSize = expectedLen * sizeof(wchar_t); aafUInt32 commentBufSize = 0; checkResult(pEvent->GetCommentBufLen(&commentBufSize)); checkExpression(commentBufSize == expectedSize, AAFRESULT_TEST_FAILED); // Validate the event comment. checkExpression(commentBufSize <= sizeof(eventComment), AAFRESULT_TEST_FAILED); checkResult(pEvent->GetComment(eventComment, commentBufSize)); checkExpression(0 == memcmp(eventComment, _eventComment, commentBufSize), AAFRESULT_TEST_FAILED); } catch (HRESULT& rHR) { hr = rHR; // fall through and handle cleanup } // Cleanup local references if (pEvent) { pEvent->Release(); pEvent = NULL; } if (pSegment) { pSegment->Release(); pSegment = NULL; } if (pEventMobSlot) { pEventMobSlot->Release(); pEventMobSlot = NULL; } if (pMobSlot) { pMobSlot->Release(); pMobSlot = NULL; } if (pEnumSlots) { pEnumSlots->Release(); pEnumSlots = NULL; } if (pMob) { pMob->Release(); pMob = NULL; } // Propogate the error if necessary. checkResult(hr); }
extern int main(int argc, char *argv[]) { const char *filename_cstr = "test.aaf"; #ifndef _MSC_VER setlocale (LC_ALL, "en_US.UTF-8"); #endif if (argc >= 2) { filename_cstr = argv[1]; } // convert C str to wide string aafWChar filename[FILENAME_MAX]; size_t status = mbstowcs(filename, filename_cstr, sizeof(filename)); if (status == (size_t)-1) { fprintf(stderr, "mbstowcs failed for \"%s\"\n", filename_cstr); return 1; } remove(filename_cstr); IAAFFile *pFile = NULL; int mode = 0; aafProductIdentification_t productID; aafProductVersion_t TestVersion = {1, 1, 0, 0, kAAFVersionUnknown}; productID.companyName = (aafCharacter*)L"HSC"; productID.productName = (aafCharacter*)L"String Tester"; productID.productVersion = &TestVersion; productID.productVersionString = NULL; productID.productID = TestProductID; productID.platform = (aafCharacter*)L"Linux"; // Create new AAF file check(AAFFileOpenNewModify(filename, mode, &productID, &pFile)); // Create a simple Mob IAAFClassDef *classDef = NULL; IAAFMob *pMob = NULL; IAAFHeader *pHeader = NULL; IAAFDictionary *pDictionary = NULL; check(pFile->GetHeader(&pHeader)); check(pHeader->GetDictionary(&pDictionary)); check(pDictionary->LookupClassDef(AUID_AAFMasterMob, &classDef)); check(classDef->CreateInstance(IID_IAAFMob, (IUnknown **)&pMob)); classDef->Release(); check(pMob->SetMobID(TEST_MobID)); // UTF-8 for codepoint U+1D11E (musical G Clef): 0xf0,0x9d,0x84,0x9e // UTF-8 for codepoint U+1D122 (musical F Clef): 0xf0,0x9d,0x84,0xa2 // http://unicode.org/charts/PDF/U1D100.pdf // http://en.wikipedia.org/wiki/UTF-8 aafCharacter *mobname; const unsigned char inputStr[] = { 0xf0,0x9d,0x84,0x9e, // U+1D11E 0xf0,0x9d,0x84,0xa2, // U+1D122 0x4d, 0x6f, 0x62, // 'M' 'o' 'b' 0x0 }; // Convert UTF-8 inputStr to native wchar_t representation (UTF-32 Unix, UTF-16 Windows) int wlen = 0, n; #ifndef _MSC_VER int ret; char *p = (char *)inputStr; while ((ret = mblen(p, 4)) > 0) { ++wlen; p+=ret; } mobname = new aafCharacter[wlen+1]; n = mbstowcs(mobname, (const char *)inputStr, wlen+1); if (n == -1) { fprintf (stderr, "mbstowcs returned -1. Invalid multibyte string\n"); exit(1); } #else // Under Windows we must use MultiByteToWideChar() to get correct UTF-8 conversion to UTF-16 // since mbstowcs() is broken for UTF-8. wlen = MultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, (LPCSTR)inputStr, -1, NULL, 0); if (wlen == 0) { fprintf (stderr, "MultiByteToWideChar returned 0. Invalid multibyte string\n"); exit(1); } mobname = new aafCharacter[wlen]; n = MultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, (LPCSTR)inputStr, -1, mobname, wlen); if (n == 0) { fprintf (stderr, "MultiByteToWideChar returned 0. Invalid multibyte string\n"); exit(1); } #endif // SetName() calls OMSimpleProperty::set() which does a memcpy of the mobname string // to an OMByte* variable 'bits()' at OMProperty.cpp:399 // Found by setting an rwatch on mobname address. check(pMob->SetName(mobname)); aafUInt32 size_before = 0; check(pMob->GetNameBufLen(&size_before)); check(pHeader->AddMob(pMob)); pMob->Release(); pHeader->Release(); pDictionary->Release(); // All the work of storing to disk happens during Save() // The bits() variable is next read in OMType::contract() at OMType.cpp:137 // which is called by ImplAAFTypeDefCharacter::externalize() at ImplAAFTypeDefCharacter.cpp:307 // which is called by ImplAAFTypeDefString::externalize() at ImplAAFTypeDefString.cpp:584 // which is called by OMSSStoredObject::save() at OMSSStoredObject.cpp:382 check(pFile->Save()); check(pFile->Close()); pFile->Release(); // OMCharacterStringProperty<CharacterType>::stringLength() at OMVariableSizePropertyT.h:80 // calculates string length of AAF string properties // Read AAF file back in check(AAFFileOpenExistingRead(filename, mode, &pFile)); // Get the Mob check(pFile->GetHeader(&pHeader)); check(pHeader->LookupMob(TEST_MobID, &pMob)); aafUInt32 size_after = 0; check(pMob->GetNameBufLen(&size_after)); aafCharacter *mobname_after = new aafCharacter[size_after]; check(pMob->GetName(mobname_after, size_after)); // Compare Mob name before storing to disk with Mob name read back from disk int test_result = 0; if (size_before != size_after) { printf("size_before=%d != size_after=%d\n", size_before, size_after); test_result = 1; } else { if (memcmp(mobname, mobname_after, size_before) != 0) { printf("wchar_t* mobname and wchar_t* mobname_after differ:\n"); printf(" %s\n", hexDump(mobname, size_before)); printf(" %s\n", hexDump(mobname_after, size_after)); test_result = 1; } } // Check if the multibyte (UTF-8) versions of mobname and mobname_after match. char *outputStr; #ifndef _MSC_VER wlen = wcslen(mobname_after)*sizeof(aafCharacter) + 1; outputStr = new char [wlen]; n = wcstombs (outputStr, mobname_after, wlen); if (n == -1) { fprintf(stderr, "Could not convert mobname_after to multibyte str\n"); exit(1); } #else wlen = WideCharToMultiByte(CP_UTF8, 0, mobname_after, -1, NULL, 0, NULL, NULL); if (wlen == 0) { fprintf (stderr, "Failed to convert mobname_after to multibyte string\n"); exit(1); } outputStr = new char[wlen]; wlen = WideCharToMultiByte(CP_UTF8, 0, mobname_after, -1, outputStr, wlen, NULL, NULL); #endif if (strlen((char *)inputStr) != strlen(outputStr)) { fprintf(stderr, "UTF-8 version of string: input length(%d) != output length(%d)\n", (int)strlen((char *)inputStr), (int)strlen(outputStr)); test_result = 1; } if (strcmp((char *)inputStr, outputStr) != 0) { fprintf(stderr, "UTF-8 version of string: input and output strings differ\n"); printf(" %s\n", hexDump(inputStr, strlen((char *)inputStr))); printf(" %s\n", hexDump(outputStr, strlen(outputStr))); test_result = 1; } pMob->Release(); pHeader->Release(); check(pFile->Close()); pFile->Release(); delete [] mobname; delete [] mobname_after; return test_result; }