[Helix-client-dev] CR/CN: Introduced differentiated program return codes for simpler errors [GMPMetaEditor branch]
Petar Basic <[email protected]> Sun, 17 Jan 2010 18:44:02 +0100
| Newsgroups | gmane.comp.multimedia.helix.devel |
|---|---|
| Message-ID | <[email protected]> |
Modified by: pbasic at real.com Date: 2010/01/17 Project: GMPMetaEditor (meta3gp.exe) Synopsis: Introduced differentiated program return codes for simpler errors [GMPMetaEditor branch] Details: Added program return codes for each error condition that the main executable can easily detect: RC_SUCCESS RC_ERROR_GENERIC RC_ERROR_BAD_COMMAND_LINE RC_ERROR_CANNOT_OPEN_LOG_FILE RC_ERROR_MISSING_ENV_VAR RC_ERROR_CANNOT_LOAD_DLL RC_ERROR_CANNOT_INIT_PROGRAM_OBJECT RC_ERROR_CANNOT_OPEN_INPUT_XML_FILE RC_ERROR_BAD_INPUT_XML_FILE RC_ERROR_INPUT_MEDIA_FILE_NOT_SPECIFIED RC_ERROR_CANNOT_OPEN_INPUT_MEDIA_FILE RC_ERROR_OUTPUT_MEDIA_FILE_EXISTS RC_ERROR_SAME_INPUT_OUTPUT_MEDIA_FILE RC_ERROR_CANNOT_OPEN_INPUT_PICTURE_FILE RC_ERROR_UNSUPPORTED_INPUT_PICTURE_TYPE RC_ERROR_CANNOT_OPEN_INPUT_UITS_FILE RC_ERROR_UNSUPPORTED_INPUT_UITS_ENCODING RC_ERROR_OUTPUT_PICTURE_FILE_EXISTS RC_ERROR_CANNOT_OUTPUT_PICTURE_FILE RC_ERROR_OUTPUT_UITS_FILE_EXISTS RC_ERROR_CANNOT_OUTPUT_UITS_FILE RC_ERROR_OUTPUT_XML_FILE_EXISTS RC_ERROR_CANNOT_OUTPUT_XML_FILE RC_ERROR_PROCESSING_MEDIA_FILE Deep Helix errors are all reported as RC_ERROR_PROCESSING_MEDIA_FILE. Files Modified: datatype/tools/dtdriver/apps/meta3gp/main.cpp Platforms and Profiles Affected: All Image Size and Heap Use impact: None Platforms and Profiles Build Verified: system id: win32-i386-vc7, sunos-5.10-sparc-studio11 profile: helix-client-all-defines Platforms and Profiles Functionality Verified: x86 Windows XP SP2 Sparc SunOS 5.10 Branch: GMPMetaEditor Copyright assignment: I am a RealNetworks employee or contractor. _______________________________________________ Helix-client-dev mailing list [email protected] http://lists.helixcommunity.org/mailman/listinfo/helix-client-dev
datatype_tools_dtdriver_apps_meta3gp.diff
(application/octet-stream, 47.7 KB)
Index: main.cpp
===================================================================
RCS file: /cvsroot/datatype/tools/dtdriver/apps/meta3gp/main.cpp,v
retrieving revision 1.7.2.3
diff -d -H -w -U30 -r1.7.2.3 main.cpp
--- main.cpp 16 Jan 2010 22:34:35 -0000 1.7.2.3
+++ main.cpp 17 Jan 2010 17:32:08 -0000
@@ -209,60 +209,93 @@
#define OPTION_STRING_TRACKSTOTAL "trackstotal"
#define OPTION_STRING_DISKNUMBER "disk"
#define OPTION_STRING_DISKSTOTAL "diskstotal"
// 3GPP specific metadata
#define OPTION_STRING_LANGUAGE_CODE "lang"
#define OPTION_STRING_COPYRIGHT "copyright"
#define OPTION_STRING_RATING_ENTITY "rtngent"
#define OPTION_STRING_RATING_CRITERIA "rtngcrit"
#define OPTION_STRING_RATING_INFO "rtnginfo"
#define OPTION_STRING_CLASSIFICATION_ENTITY "clsent"
#define OPTION_STRING_CLASSIFICATION_TABLE "clstbl"
#define OPTION_STRING_CLASSIFICATION_INFO "clsinfo"
#define OPTION_STRING_KEYWORD_ADD "addkwd"
#define OPTION_STRING_KEYWORD_REMOVE "remkwd"
#define OPTION_STRING_KEYWORD_CLEAR "clrkwd"
#define OPTION_STRING_LOCATION_NAME "locname"
#define OPTION_STRING_LOCATION_ASTRONOMICAL_BODY "locastro"
#define OPTION_STRING_LOCATION_ADDITIONAL_NOTES "locnotes"
#define OPTION_STRING_LOCATION_ROLE "locrole"
#define OPTION_STRING_LOCATION_LONGITUDE "loclong"
#define OPTION_STRING_LOCATION_LATITUDE "loclat"
#define OPTION_STRING_LOCATION_ALTITUDE "localt"
/****************************************************************************
+* Program return codes
+*/
+#define RC_SUCCESS 0
+
+#define RC_ERROR_GENERIC 10
+#define RC_ERROR_BAD_COMMAND_LINE 11
+#define RC_ERROR_CANNOT_OPEN_LOG_FILE 12
+
+#define RC_ERROR_MISSING_ENV_VAR 21
+#define RC_ERROR_CANNOT_LOAD_DLL 22
+#define RC_ERROR_CANNOT_INIT_PROGRAM_OBJECT 23
+
+#define RC_ERROR_CANNOT_OPEN_INPUT_XML_FILE 31
+#define RC_ERROR_BAD_INPUT_XML_FILE 32
+#define RC_ERROR_INPUT_MEDIA_FILE_NOT_SPECIFIED 33
+#define RC_ERROR_CANNOT_OPEN_INPUT_MEDIA_FILE 34
+#define RC_ERROR_OUTPUT_MEDIA_FILE_EXISTS 35
+#define RC_ERROR_SAME_INPUT_OUTPUT_MEDIA_FILE 36
+#define RC_ERROR_CANNOT_OPEN_INPUT_PICTURE_FILE 37
+#define RC_ERROR_UNSUPPORTED_INPUT_PICTURE_TYPE 38
+#define RC_ERROR_CANNOT_OPEN_INPUT_UITS_FILE 39
+#define RC_ERROR_UNSUPPORTED_INPUT_UITS_ENCODING 40
+#define RC_ERROR_OUTPUT_PICTURE_FILE_EXISTS 41
+#define RC_ERROR_CANNOT_OUTPUT_PICTURE_FILE 42
+#define RC_ERROR_OUTPUT_UITS_FILE_EXISTS 43
+#define RC_ERROR_CANNOT_OUTPUT_UITS_FILE 44
+#define RC_ERROR_OUTPUT_XML_FILE_EXISTS 45
+#define RC_ERROR_CANNOT_OUTPUT_XML_FILE 46
+
+#define RC_ERROR_PROCESSING_MEDIA_FILE 100
+
+
+/****************************************************************************
* Help display utilities
*/
class OptionDesc
{
public:
OptionDesc(const char* option_ = 0, const char* option_args_ = 0, const char* desc_ = 0,
int arg_count_ = 0, const char* xpath_ = 0)
{
option = option_;
option_args = option_args_;
desc = desc_;
arg_count = arg_count_;
xpath = xpath_;
}
UINT32 GetLeftColumnWidth()
{
UINT32 len = 0;
if(option)
{
len += 2 + strlen(option); //leading whitespace and option prefix
if(option_args)
{
len += 1 + strlen(option_args); //whitespace separator and option args
}
}
return len;
}
CHXString BuildLine(UINT32 leftColumnWidth)
@@ -969,175 +1002,191 @@
return HXR_OK;
}
if(MetaInfo::IsItemSupportedByAnyFlavor(MetaInfo::ArrayMetaItem_Keywords, metaFlavorFlags))
{
EncodedString* pEncStr = new EncodedString(option->OptionValueUTF8);
if(pEncStr && MetaInfo::IsKeywordValidForFlavors(*pEncStr, metaFlavorFlags))
{
aKeywords.Add(pEncStr);
return HXR_OK;
}
delete pEncStr;
ReportInvalidValueForOption(option->OptionName, option->OptionValueUTF8);
return HXR_PARSE_ERROR;
}
ReportUnsupportedMetaStyleOption(option->OptionName);
return HXR_PARSE_ERROR;
}
inline HX_RESULT ProcessDependentKeywordStringOption(eCommandLineProcessorPhase phase, InputOption* option,
CHXPtrArray& aKeywords, UINT32 metaFlavorFlags)
{
return ProcessKeywordStringOption((phase != CLPP_DependentOptions),
option, aKeywords, metaFlavorFlags);
}
-HX_RESULT ProcessXMLFileStringOption(bool bSkipArgOnly, InputOption* option, MetaInfo& metainfo,
+HX_RESULT ProcessXMLFileStringOption(int& progRetCode, bool bSkipArgOnly, InputOption* option, MetaInfo& metainfo,
MetaInfo::eStringMetaItem itemName, UINT32 metaFlavorFlags)
{
if(option->OptionValueUTF8.IsEmpty())
{
return HXR_PARSE_ERROR;
}
if(bSkipArgOnly)
{
return HXR_OK;
}
if(MetaInfo::IsItemSupportedByAnyFlavor(itemName, metaFlavorFlags))
{
// read-in the file contents
CHXString sFileName = option->GetEffectiveOptionValueCCP();
- if(!sFileName.IsEmpty())
+ if(!sFileName.IsEmpty() && CHXFileSpecUtils::FileExists(CHXFileSpecifier(sFileName)))
{
EncodedString sXML;
HX_RESULT retVal = MetaInfo::LoadXMLStringFromFile((const char*)sFileName, sXML);
+ if(FAILED(retVal))
+ {
+ printf("Unsupported encoding in UITS file: %s\n", (const char*)sFileName);
+ progRetCode = RC_ERROR_UNSUPPORTED_INPUT_UITS_ENCODING;
+ return HXR_FAILED;
+ }
+
if(SUCCEEDED(retVal) &&
MetaInfo::IsItemValueValidForFlavors(itemName, sXML, metaFlavorFlags) &&
SUCCEEDED(metainfo.SetStringItem(itemName, sXML)))
{
return HXR_OK;
}
}
+ else
+ {
+ printf("Failed to open UITS file: %s\n", (const char*)sFileName);
+ progRetCode = RC_ERROR_CANNOT_OPEN_INPUT_UITS_FILE;
+ return HXR_FAILED;
+ }
ReportInvalidValueForOption(option->OptionName, option->OptionValueUTF8);
return HXR_PARSE_ERROR;
}
ReportUnsupportedMetaStyleOption(option->OptionName);
return HXR_PARSE_ERROR;
}
HX_RESULT ProcessRemovePictureOption(bool bSkipArgOnly, InputOption* option,
CHXPtrArray& aRemovedPictureTypes, UINT32 metaFlavorFlags)
{
if(option->OptionValueUTF8.IsEmpty())
{
return HXR_PARSE_ERROR;
}
if(bSkipArgOnly)
{
return HXR_OK;
}
if(MetaInfo::IsItemSupportedByAnyFlavor(MetaInfo::ArrayMetaItem_Pictures, metaFlavorFlags))
{
EncodedString sVal = option->OptionValueUTF8;
UINT32 uVal = 0;
if(PropTools::ExtractUInt32(uVal, sVal) &&
MetaInfo::IsAPICPictureTypeValidForFlavors(uVal, metaFlavorFlags))
{
aRemovedPictureTypes.AddIfUnique((void*)uVal);
return HXR_OK;
}
ReportInvalidValueForOption(option->OptionName, option->OptionValueUTF8);
return HXR_PARSE_ERROR;
}
ReportUnsupportedMetaStyleOption(option->OptionName);
return HXR_PARSE_ERROR;
}
-HX_RESULT ProcessAddPictureOption(bool bSkipArgOnly, InputOption* option,
+HX_RESULT ProcessAddPictureOption(int& progRetCode, bool bSkipArgOnly, InputOption* option,
CHXPtrArray& aAddedAPICFrames, UINT32 metaFlavorFlags)
{
if(option->OptionValueUTF8.IsEmpty())
{
return HXR_PARSE_ERROR;
}
if(bSkipArgOnly)
{
return HXR_OK;
}
if(MetaInfo::IsItemSupportedByAnyFlavor(MetaInfo::ArrayMetaItem_Pictures, metaFlavorFlags))
{
ID3Tools::APICFrame* pFrame = new ID3Tools::APICFrame;
if(!pFrame)
{
+ progRetCode = RC_ERROR_CANNOT_INIT_PROGRAM_OBJECT;
return HXR_OUTOFMEMORY;
}
// process image file
HX_RESULT retVal = HXR_FAILED;
CHXString sFileName = option->GetEffectiveOptionValueCCP();
- if(!sFileName.IsEmpty())
+ if(!sFileName.IsEmpty() && CHXFileSpecUtils::FileExists(CHXFileSpecifier(sFileName)))
{
// load image, accept only known MIME types
retVal = pFrame->LoadPictureDataFromImageFile((const char*)sFileName, TRUE);
// check if frame is acceptable
- if(SUCCEEDED(retVal))
- {
- if(!MetaInfo::IsAPICFrameValidForFlavors(*pFrame, metaFlavorFlags))
+ if(SUCCEEDED(retVal) && !MetaInfo::IsAPICFrameValidForFlavors(*pFrame, metaFlavorFlags))
{
retVal = HXR_FAILED;
}
- }
- }
if(FAILED(retVal))
{
- printf("Invalid image file for option %s: %s\n",
- (const char*)option->OptionName, (const char*)sFileName);
+ printf("Unsupported picture type in file: %s\n", (const char*)sFileName);
+ progRetCode = RC_ERROR_UNSUPPORTED_INPUT_PICTURE_TYPE;
+ }
+ }
+ else
+ {
+ printf("Failed to open picture file: %s\n", (const char*)sFileName);
+ progRetCode = RC_ERROR_CANNOT_OPEN_INPUT_PICTURE_FILE;
}
// export frame
if(SUCCEEDED(retVal) && pFrame)
{
if(!aAddedAPICFrames.AddIfUnique(pFrame))
{
retVal = HXR_FAILED;
}
}
if(FAILED(retVal))
{
// cleanup
HX_DELETE(pFrame);
}
return retVal;
}
ReportUnsupportedMetaStyleOption(option->OptionName);
return HXR_PARSE_ERROR;
}
// Only moves argVars position if successful
HX_RESULT CopyOptionArgumentString(ArgVars& argVars, EncodedString& sOut, HXBOOL bOptional = FALSE)
{
sOut.Clear();
const TCHAR* pVal = argVars.CurrentArg(1, bOptional, TRUE);
@@ -1291,71 +1340,71 @@
case 1:
{
// one argument
retVal = CopyOptionArgumentString(argVars, optionArgument, FALSE);
break;
}
default:
// unsupported number of option arguments
retVal = HXR_PARSE_ERROR;
continue;
}
if(FAILED(retVal) && !bStrictMode)
{
retVal = HXR_OK;
argVars.MovePosition(numArgs);
continue;
}
if(SUCCEEDED(retVal))
{
inputOptions.Add(new InputOption(strOption, optionArgument, EncodedString()));
}
}
return retVal;
}
HX_RESULT ParseXMLInputOptions(IHXCommonClassFactory* pCommonClassFactory, CHXXmlInputParser* pInputParser,
- InputOption* option, CParsedXmlPairs* parsedXmlResults)
+ const CHXString& strInputXMLFilename, CParsedXmlPairs* parsedXmlResults)
{
- if(option->OptionValueUTF8.IsEmpty())
+ if(strInputXMLFilename.IsEmpty())
{
return HXR_FAIL;
}
- FILE* fp = fopen((const char*)option->GetEffectiveOptionValueCCP(), "r");
+ FILE* fp = fopen((const char*)strInputXMLFilename, "r");
if(fp == NULL)
{
- printf("Unable to open file: %s\n", (const char*)option->GetEffectiveOptionValueCCP());
+ printf("Unable to open file: %s\n", (const char*)strInputXMLFilename);
return HXR_FAIL;
}
HX_RESULT retVal = HXR_OK;
retVal = pInputParser->Start(parsedXmlResults);
ULONG32 uParserBufferSize = 64 * 1024;
if(SUCCEEDED(retVal))
{
// create temporary buffer for manifest chunks
IHXBuffer* pBuffer = NULL;
retVal = CreateBufferCCF(pBuffer, pCommonClassFactory);
if(SUCCEEDED(retVal))
{
pBuffer->SetSize(uParserBufferSize);
// read manifest, chunk by chunk
while(true)
{
size_t nItemsRead = fread(pBuffer->GetBuffer(), 1, uParserBufferSize, fp);
if(nItemsRead != 0)
{
if(uParserBufferSize != nItemsRead)
{
pBuffer->SetSize(nItemsRead);
}
// parse chunk
HXBOOL bIsFinal = uParserBufferSize != nItemsRead;
@@ -1569,65 +1618,65 @@
}
STDMETHOD(OnStreamDone)(UINT16 unStreamNumber)
{
#ifdef HELIX_FEATURE_METAEDIT_AUDIO_HASH
if(m_vars.GenerateHash && !m_bHashGenerated)
{
sha256_done(&m_vars.HashState, m_vars.SHAHash);
// make sure, that even if there is more than one call to OnStreamDone, we execute sha finalizer just one time
m_bHashGenerated = TRUE;
}
#endif
return HXR_OK;
}
private:
LONG32 m_lRefCount;
MetaProcessorVars& m_vars;
IUnknown* m_pContext;
HXBOOL m_bHashGenerated;
};
/****************************************************************************
* Main entry point
*/
int TMAIN(int argc, TCHAR* argv[])
{
// initialize variables
HX_RESULT retVal = HXR_OK;
+ int progRetCode = RC_SUCCESS;
UINT32 startTime = 0;
CHXFileSpecifier exeFileSpec;
HXBOOL bUsingLog = FALSE;
- HXBOOL bFailedToOpenLog = FALSE;
DLLAccess* pDLLAccess = 0;
FPHXMEDIAPLATFORMOPEN fpHXMediaPlatformOpen = 0;
FPHXCREATEMEDIAPLATFORM fpHXCreateMediaPlatform = 0;
FPHXMEDIAPLATFORMCLOSE fpHXMediaPlatformClose = 0;
IHXMediaPlatform* pMediaPlatform = 0;
IHXCommonClassFactory* pCommonClassFactory = 0;
CHXXmlInputParser* pInputParser = 0;
IHXMetaDataEditor* pEditor = 0;
CResponse* pResponse = 0;
CProcessor* pProcessor = 0;
IHXValues* pOptions = 0;
char pDllPath[_MAX_PATH] = {0};
char pDllFile[_MAX_PATH] = {0};
const char* pszHelixPluginPath = 0;
CHXString strInputFileName;
CHXString strOutputFileName;
CHXString strPictureFileNamePrefix;
CHXString strUITSDataOutputFileName;
CHXString strMetaStyleName;
HXBOOL bDisplayHelp = FALSE;
HXBOOL bOverwriteFile = FALSE;
HXBOOL bPrintMetaData = FALSE;
HXBOOL bExtractPicturesToFiles = FALSE;
HXBOOL bUTF16Output = FALSE;
UINT32 ulMetaDataID3VersionOutput = METADATAID3VERSION_240;
@@ -1710,289 +1759,321 @@
ArgVars argVars(argc, argv, optionReg);
InputOptions inputOptions;
// scan for log option, but do not print syntax errors yet
retVal = ParseCommandLineInputOptions(argVars, optionReg, inputOptions, FALSE, FALSE);
// see if we should redirect output to a log file
CHXString sLogFilename;
InputOption* pOptionLogfile = inputOptions.GetOption(OPTION_STRING_LOGFILE);
if(pOptionLogfile)
{
sLogFilename = pOptionLogfile->GetEffectiveOptionValueCCP();
if(!sLogFilename.IsEmpty())
{
// see if we can actually open the log file before disconnecting from console
FILE* fpLog = fopen((const char*)sLogFilename, "a");
if(fpLog)
{
bUsingLog = TRUE;
// reopen standard output and standard error in append mode
freopen((const char*)sLogFilename, "a", stdout);
freopen((const char*)sLogFilename, "a", stderr);
// we can close our local pointer now
fclose(fpLog);
fpLog = 0;
}
else
{
- bFailedToOpenLog = TRUE;
+ progRetCode = RC_ERROR_CANNOT_OPEN_LOG_FILE;
}
}
}
if(bUsingLog)
{
// echo current time to log
printf("\n========== %s ==========\n\n", (const char*)GetUTCTimeString());
// echo command line to log
argVars.DumpCommandLine();
}
// echo program startup header
DisplayProgramInfo();
// clear results of previous parsing
inputOptions.Clear();
// parse the command line again, this time print errors
retVal = ParseCommandLineInputOptions(argVars, optionReg, inputOptions, TRUE, TRUE);
- if(bFailedToOpenLog)
+ // reporting command line error has precedence over reporting log file problem
+ if(FAILED(retVal))
+ {
+ progRetCode = RC_ERROR_BAD_COMMAND_LINE;
+ }
+ else if(progRetCode == RC_ERROR_CANNOT_OPEN_LOG_FILE)
{
printf("Failed to open log file: [%s]\n\n", (const char*)sLogFilename);
+ retVal = HXR_FAILED;
}
if(FAILED(retVal))
{
goto cleanup;
}
// initialize Helix DNA client media-platform
pDLLAccess = new DLLAccess();
if(!pDLLAccess)
{
retVal = HXR_OUTOFMEMORY;
+ progRetCode = RC_ERROR_CANNOT_INIT_PROGRAM_OBJECT;
goto cleanup;
}
// extract plugin directory
#ifdef _WINDOWS
exeFileSpec = CHXFileSpecUtils::GetCurrentApplication();
strncpy(pDllPath, (const char*)exeFileSpec.GetParentDirectory().GetPathName(), _MAX_PATH);
snprintf(pDllFile, _MAX_PATH, "%s\\%s", pDllPath, "hxmedpltfm.dll");
#else
pszHelixPluginPath = getenv(PLUGIN_PATH_ENV_VAR_NAME);
if(pszHelixPluginPath && (strlen(pszHelixPluginPath) > 0))
{
strncpy(pDllPath, pszHelixPluginPath, _MAX_PATH);
snprintf(pDllFile, _MAX_PATH, "%s/%s", pDllPath, "hxmedpltfm.so");
}
else
{
printf("Missing environment variable %s.\n", PLUGIN_PATH_ENV_VAR_NAME);
+
+ retVal = HXR_FAILED;
+ progRetCode = RC_ERROR_MISSING_ENV_VAR;
goto cleanup;
}
#endif
pDllPath[_MAX_PATH - 1] = '\0';
pDllFile[_MAX_PATH - 1] = '\0';
if(pDLLAccess->open(pDllFile) != DLLAccess::DLL_OK)
{
printf("Failed to access Helix DNA client media-platform library file: %s\n", pDllFile);
const char* szError = pDLLAccess->getErrorString();
if(szError)
{
printf("Error description: %s\n", szError);
}
+ retVal = HXR_FAILED;
+ progRetCode = RC_ERROR_CANNOT_LOAD_DLL;
goto cleanup;
}
// initialize Helix media-platform
fpHXMediaPlatformOpen = (FPHXMEDIAPLATFORMOPEN) pDLLAccess->getSymbol("HXMediaPlatformOpen");
fpHXCreateMediaPlatform = (FPHXCREATEMEDIAPLATFORM) pDLLAccess->getSymbol("HXCreateMediaPlatform");
fpHXMediaPlatformClose = (FPHXMEDIAPLATFORMCLOSE) pDLLAccess->getSymbol("HXMediaPlatformClose");
if(!fpHXMediaPlatformOpen || !fpHXCreateMediaPlatform || !fpHXMediaPlatformClose)
{
retVal = HXR_FAILED;
}
if(SUCCEEDED(retVal))
{
retVal = fpHXMediaPlatformOpen();
}
if(SUCCEEDED(retVal))
{
retVal = fpHXCreateMediaPlatform((IHXMediaPlatform**)&pMediaPlatform);
}
if(SUCCEEDED(retVal))
{
retVal = pMediaPlatform->AddPluginPath("Meta3GP", pDllPath);
}
if(SUCCEEDED(retVal))
{
retVal = pMediaPlatform->Init(0);
}
if(SUCCEEDED(retVal))
{
retVal = pMediaPlatform->QueryInterface(IID_IHXCommonClassFactory, (void**)&pCommonClassFactory);
}
if(FAILED(retVal))
{
printf("Failed to initialize Helix DNA client media-platform.\n");
+
+ progRetCode = RC_ERROR_CANNOT_INIT_PROGRAM_OBJECT;
goto cleanup;
}
// initialize meta-data editor response object
pResponse = new CResponse();
HX_ADDREF(pResponse);
if(!pResponse)
{
retVal = HXR_OUTOFMEMORY;
}
if(FAILED(retVal))
{
printf("Failed to initialize Helix meta-data editor response object.\n");
+ progRetCode = RC_ERROR_CANNOT_INIT_PROGRAM_OBJECT;
goto cleanup;
}
// initialize meta-data processor object
pProcessor = new CProcessor(metaProcessorVars);
HX_ADDREF(pProcessor);
if(!pProcessor)
{
retVal = HXR_OUTOFMEMORY;
}
if(FAILED(retVal))
{
printf("Failed to initialize Helix meta-data processor object.\n");
+ progRetCode = RC_ERROR_CANNOT_INIT_PROGRAM_OBJECT;
goto cleanup;
}
// initialize meta-data editor plugin
retVal = CreateInstanceCCF_QI(CLSID_IHXMetaDataEditor, IID_IHXMetaDataEditor,
(void**)&pEditor, pCommonClassFactory);
if(SUCCEEDED(retVal))
{
retVal = pEditor->InitMetaDataEditor(pCommonClassFactory);
}
if(FAILED(retVal))
{
printf("Failed to initialize Helix meta-data editor plugin.\n");
+ progRetCode = RC_ERROR_CANNOT_INIT_PROGRAM_OBJECT;
goto cleanup;
}
// initialize xml parser
if(SUCCEEDED(retVal))
{
retVal = HXR_OUTOFMEMORY;
pInputParser = new CHXXmlInputParser();
if(pInputParser)
{
pInputParser->AddRef();
retVal = HXR_OK;
}
}
if(SUCCEEDED(retVal))
{
retVal = pInputParser->Init(pCommonClassFactory);
}
if(FAILED(retVal))
{
printf("Failed to initialize XML parser.\n");
+ progRetCode = RC_ERROR_CANNOT_INIT_PROGRAM_OBJECT;
goto cleanup;
}
// parse XML input file
if(SUCCEEDED(retVal))
{
- InputOption* optionXmlIn = inputOptions.GetOption(CHXString(OPTION_STRING_XMLINPUTFILE));
- if(optionXmlIn && !optionXmlIn->OptionValueUTF8.IsEmpty())
+ InputOption* pOptionXmlIn = inputOptions.GetOption(CHXString(OPTION_STRING_XMLINPUTFILE));
+ CHXString strInputXMLFilename = pOptionXmlIn ? pOptionXmlIn->GetEffectiveOptionValueCCP() : CHXString();
+
+ if(!strInputXMLFilename.IsEmpty() && !CHXFileSpecUtils::FileExists(CHXFileSpecifier(strInputXMLFilename)))
{
- printf("Processing XML input file:\n");
+ printf("XML input file [%s] not found.\n", (const char*)strInputXMLFilename);
+ retVal = HXR_FAIL;
+ progRetCode = RC_ERROR_CANNOT_OPEN_INPUT_XML_FILE;
+ }
+
+ if(SUCCEEDED(retVal) && !strInputXMLFilename.IsEmpty())
+ {
+ printf("Processing XML input file [%s].\n", (const char*)strInputXMLFilename);
CParsedXmlPairs parsedXmlResults;
optionReg.InitializeXmlPairs(&parsedXmlResults);
- retVal = ParseXMLInputOptions(pCommonClassFactory, pInputParser, optionXmlIn, &parsedXmlResults);
+ retVal = ParseXMLInputOptions(pCommonClassFactory, pInputParser, strInputXMLFilename, &parsedXmlResults);
if(SUCCEEDED(retVal))
{
// merge parsed results into inputOptions
CHXPtrArray *xmlPairs = parsedXmlResults.GetAllPairs();
for(int i = 0; i < xmlPairs->GetSize(); i++)
{
XmlPair *pair = (XmlPair*)xmlPairs->GetAt(i);
OptionDesc* optDesc = optionReg.GetOptionDescWithPath(pair->xmlPath);
// Add only results of XML file parsing which have non-empty value.
if((optDesc != NULL) && !pair->xmlValueUTF8.IsEmpty())
{
CHXString strName = optDesc->GetOptionString();
InputOption* inOpt = inputOptions.GetOption(strName);
if(inOpt == NULL)
{
inputOptions.Add(new InputOption(strName, EncodedString(), pair->xmlValueUTF8));
}
else
{
inOpt->XmlOptionValueUTF8 = pair->xmlValueUTF8;
}
printf("-%s taken from location [%s], value=[", (const char*)strName, (const char*)pair->xmlPath);
EncStrUtils::PrintTextUTF8(pair->xmlValueUTF8.GetData());
printf("]\n");
}
}
printf("\n");
}
+ else
+ {
+ printf("Error parsing XML input file.\n");
+ progRetCode = RC_ERROR_BAD_INPUT_XML_FILE;
+ }
}
}
// Process final combination of command-line and XML file input.
// The first phase seeks for independent arguments, the second phase seeks for dependent arguments.
eCommandLineProcessorPhase clpp = CLPP_IndependentOptions;
while(SUCCEEDED(retVal) && (clpp != CLPP_Done))
{
for(inputOptions.ResetPosition(0); SUCCEEDED(retVal) && !inputOptions.ReachedEndPosition();
inputOptions.MovePosition(1))
{
InputOption* option = inputOptions.CurrentOption();
CHXString strOption = option->OptionName;
if(strOption == OPTION_STRING_HELP)
{
bDisplayHelp = TRUE;
}
#ifdef _WINDOWS
else if(strOption == OPTION_STRING_ASYNCMODE)
{
g_bUseDTDriverSynchronousMode = FALSE;
}
#endif //_WINDOWS
else if(strOption == OPTION_STRING_DEFMETAPROC)
{
g_bUseDefaultMetaEditorProcessor = TRUE;
@@ -2021,60 +2102,61 @@
{
bPrintMetaData = TRUE;
}
else if(strOption == OPTION_STRING_GENERATEHASH)
{
metaProcessorVars.GenerateHash = TRUE;
}
else if(strOption == OPTION_STRING_XMLINPUTFILE)
{
// do nothing, already processed
}
else if(strOption == OPTION_STRING_METASTYLE)
{
strMetaStyleName = option->GetEffectiveOptionValueCCP();
if(clpp == CLPP_IndependentOptions)
{
if(SUCCEEDED(retVal) && !strMetaStyleName.IsEmpty())
{
if(!strMetaStyleName.CompareNoCase("3gpp"))
{
metaProcessorVars.InjectedMetaFlavors |= METADATA_FLAVOR_3GPP;
}
else if(!strMetaStyleName.CompareNoCase("itunes"))
{
metaProcessorVars.InjectedMetaFlavors |= METADATA_FLAVOR_ITUNES;
}
else
{
retVal = HXR_PARSE_ERROR;
+ progRetCode = RC_ERROR_BAD_COMMAND_LINE;
ReportInvalidValueForOption(OPTION_STRING_METASTYLE, option->GetEffectiveOptionValueUTF8());
}
}
}
}
else if(strOption == OPTION_STRING_UTF16OUTPUT)
{
bUTF16Output = TRUE;
}
else if(strOption == OPTION_STRING_ID3V240OUTPUT)
{
ulMetaDataID3VersionOutput = METADATAID3VERSION_240;
}
else if(strOption == OPTION_STRING_ID3V230OUTPUT)
{
ulMetaDataID3VersionOutput = METADATAID3VERSION_230;
}
else if(strOption == OPTION_STRING_ID3V2NOOUTPUT)
{
ulMetaDataID3VersionOutput = METADATAID3VERSION_NONE;
}
else if(strOption == OPTION_STRING_TITLE)
{
retVal = ProcessDependentStringOption(clpp, option,
metaProcessorVars, MetaInfo::StringMetaItem_Title);
}
else if(strOption == OPTION_STRING_ARTIST)
{
retVal = ProcessDependentStringOption(clpp, option,
metaProcessorVars, MetaInfo::StringMetaItem_Artist);
@@ -2089,87 +2171,87 @@
retVal = ProcessDependentStringOption(clpp, option,
metaProcessorVars, MetaInfo::StringMetaItem_Genre);
}
else if(strOption == OPTION_STRING_COMPOSER)
{
retVal = ProcessDependentStringOption(clpp, option,
metaProcessorVars, MetaInfo::StringMetaItem_Composer);
}
else if(strOption == OPTION_STRING_COMMENT)
{
retVal = ProcessDependentStringOption(clpp, option,
metaProcessorVars, MetaInfo::StringMetaItem_Description);
}
else if(strOption == OPTION_STRING_COPYRIGHT)
{
retVal = ProcessDependentStringOption(clpp, option,
metaProcessorVars, MetaInfo::StringMetaItem_Copyright);
}
else if(strOption == OPTION_STRING_TRACKNUMBER)
{
retVal = ProcessDependentUIntOption(clpp, option,
metaProcessorVars, MetaInfo::UIntMetaItem_TrackNumber);
}
else if(strOption == OPTION_STRING_YEAR)
{
retVal = ProcessDependentUIntOption(clpp, option,
metaProcessorVars, MetaInfo::UIntMetaItem_RecordingYear);
}
else if(strOption == OPTION_STRING_PICTURE_ADD)
{
- retVal = ProcessAddPictureOption((clpp != CLPP_DependentOptions),
+ retVal = ProcessAddPictureOption(progRetCode, (clpp != CLPP_DependentOptions),
option, metaProcessorVars.AddedPictures, metaProcessorVars.InjectedMetaFlavors);
}
else if(strOption == OPTION_STRING_PICTURE_REMOVE)
{
retVal = ProcessRemovePictureOption((clpp != CLPP_DependentOptions),
option, metaProcessorVars.RemovedPictures, metaProcessorVars.InjectedMetaFlavors);
}
else if(strOption == OPTION_STRING_PICTURE_CLEAR)
{
metaProcessorVars.ClearPictures = TRUE;
if((clpp == CLPP_DependentOptions) &&
!MetaInfo::IsItemSupportedByAnyFlavor(MetaInfo::ArrayMetaItem_Pictures, metaProcessorVars.InjectedMetaFlavors))
{
ReportUnsupportedMetaStyleOption(OPTION_STRING_PICTURE_CLEAR);
retVal = HXR_PARSE_ERROR;
}
}
else if(strOption == OPTION_STRING_PICTURE_EXTRACT)
{
bExtractPicturesToFiles = TRUE;
strPictureFileNamePrefix = option->GetEffectiveOptionValueCCP();
}
else if(strOption == OPTION_STRING_UITS_INSERT)
{
- retVal = ProcessXMLFileStringOption((clpp != CLPP_DependentOptions),
+ retVal = ProcessXMLFileStringOption(progRetCode, (clpp != CLPP_DependentOptions),
option, metaProcessorVars.InjectedMetaInfo, MetaInfo::StringMetaItem_UITSData,
metaProcessorVars.InjectedMetaFlavors);
}
else if(strOption == OPTION_STRING_UITS_EXTRACT)
{
strUITSDataOutputFileName = option->GetEffectiveOptionValueCCP();
}
else if(strOption == OPTION_STRING_SOFTWARE)
{
retVal = ProcessDependentStringOption(clpp, option,
metaProcessorVars, MetaInfo::StringMetaItem_GeneratorTool);
}
else if(strOption == OPTION_STRING_ENCODEDBY)
{
retVal = ProcessDependentStringOption(clpp, option,
metaProcessorVars, MetaInfo::StringMetaItem_EncodedBy);
}
else if(strOption == OPTION_STRING_GROUPING)
{
retVal = ProcessDependentStringOption(clpp, option,
metaProcessorVars, MetaInfo::StringMetaItem_Grouping);
}
else if(strOption == OPTION_STRING_ALBUMARTIST)
{
retVal = ProcessDependentStringOption(clpp, option,
metaProcessorVars, MetaInfo::StringMetaItem_AlbumArtist);
}
else if(strOption == OPTION_STRING_LYRICS)
{
retVal = ProcessDependentStringOption(clpp, option,
@@ -2278,144 +2360,150 @@
else if(strOption == OPTION_STRING_LOCATION_ALTITUDE)
{
retVal = ProcessDependentStringOption(clpp, option,
metaProcessorVars, MetaInfo::StringMetaItem_LocationAltitude);
}
else if(strOption == OPTION_STRING_KEYWORD_ADD)
{
retVal = ProcessDependentKeywordStringOption(clpp, option,
metaProcessorVars.AddedKeywords, metaProcessorVars.InjectedMetaFlavors);
}
else if(strOption == OPTION_STRING_KEYWORD_REMOVE)
{
retVal = ProcessDependentKeywordStringOption(clpp, option,
metaProcessorVars.RemovedKeywords, metaProcessorVars.InjectedMetaFlavors);
}
else if(strOption == OPTION_STRING_KEYWORD_CLEAR)
{
metaProcessorVars.ClearKeywords = TRUE;
if((clpp == CLPP_DependentOptions) &&
!MetaInfo::IsItemSupportedByAnyFlavor(MetaInfo::ArrayMetaItem_Keywords, metaProcessorVars.InjectedMetaFlavors))
{
ReportUnsupportedMetaStyleOption(OPTION_STRING_KEYWORD_CLEAR);
retVal = HXR_PARSE_ERROR;
}
}
else
{
printf("Unrecognized option: -%s\n", (const char*)strOption);
retVal = HXR_PARSE_ERROR;
+ progRetCode = RC_ERROR_BAD_COMMAND_LINE;
}
}
// update metastyles
if(clpp == CLPP_IndependentOptions)
{
// unless metastyles are explicitly specified, assume defaults according to file extension
if((metaProcessorVars.InjectedMetaFlavors == 0) && !strOutputFileName.IsEmpty())
{
CHXString sFileExt = "";
INT32 dotPos = strOutputFileName.ReverseFind('.');
if(dotPos >= 0)
{
UINT32 extLen = strOutputFileName.GetLength() - dotPos - 1;
if(extLen > 0)
{
sFileExt = strOutputFileName.Right(extLen);
}
}
if(!sFileExt.CompareNoCase("3gp"))
{
metaProcessorVars.InjectedMetaFlavors |= METADATA_FLAVOR_3GPP;
}
else if(!sFileExt.CompareNoCase("m4a"))
{
metaProcessorVars.InjectedMetaFlavors |= METADATA_FLAVOR_ITUNES;
}
}
}
// next phase
clpp = (eCommandLineProcessorPhase)(int(clpp) + 1);
}
// display usage
if(argc == 1)
{
// auto help display if started without options
bDisplayHelp = TRUE;
}
if(bDisplayHelp)
{
DisplayUsage(argv[0], optionReg);
goto cleanup;
}
- // check for semantic errors
- if(SUCCEEDED(retVal) && !bDisplayHelp)
+ // cleanup on command-line errors
+ if(FAILED(retVal))
{
- if(strInputFileName.IsEmpty())
+ if(retVal == HXR_PARSE_ERROR)
{
- printf("Input file not specified.\n");
- retVal = HXR_PARSE_ERROR;
+ progRetCode = RC_ERROR_BAD_COMMAND_LINE;
}
+ goto cleanup;
}
- // cleanup on command-line errors
- if(FAILED(retVal))
+ // check for semantic errors
+ if(SUCCEEDED(retVal) && strInputFileName.IsEmpty())
{
- goto cleanup;
+ printf("Input file not specified.\n");
+ retVal = HXR_PARSE_ERROR;
+ progRetCode = RC_ERROR_INPUT_MEDIA_FILE_NOT_SPECIFIED;
}
// input file must exist
if(SUCCEEDED(retVal) && !CHXFileSpecUtils::FileExists(CHXFileSpecifier(strInputFileName)))
{
printf("Input file [%s] not found.\n", (const char*)strInputFileName);
retVal = HXR_FAIL;
+ progRetCode = RC_ERROR_CANNOT_OPEN_INPUT_MEDIA_FILE;
}
if(SUCCEEDED(retVal) && !strOutputFileName.IsEmpty())
{
// writing to input file is not allowed
if(SUCCEEDED(retVal) && (strInputFileName == strOutputFileName))
{
printf("File [%s] cannot be used for both input and output.\n", (const char*)strOutputFileName);
retVal = HXR_FAIL;
+ progRetCode = RC_ERROR_SAME_INPUT_OUTPUT_MEDIA_FILE;
}
// output file must not exist or overwrite must be specified
if(SUCCEEDED(retVal) && NeedOverwriteConfirmation((const char*)strOutputFileName, bOverwriteFile))
{
retVal = HXR_FAIL;
+ progRetCode = RC_ERROR_OUTPUT_MEDIA_FILE_EXISTS;
}
}
if(FAILED(retVal))
{
goto cleanup;
}
// initialize options
retVal = CreateInstanceCCF_QI(CLSID_IHXValues, IID_IHXValues,
(void**)&pOptions, pCommonClassFactory);
if(SUCCEEDED(retVal))
{
retVal = pOptions->SetPropertyULONG32(SYNCHRONOUS_OPTION_NAME, g_bUseDTDriverSynchronousMode ? 1 : 0);
}
if(SUCCEEDED(retVal))
{
retVal = pOptions->SetPropertyULONG32(BLASTFILE_OPTION_NAME, bOverwriteFile ? 1 : 0);
}
if(SUCCEEDED(retVal))
{
retVal = pOptions->SetPropertyULONG32(UTF16OUTPUT_OPTION_NAME, bUTF16Output ? 1 : 0);
}
if(SUCCEEDED(retVal))
{
// Notify writer about the version of ID3 tag it should output.
retVal = pOptions->SetPropertyULONG32(METADATAID3VERSION_OPTION_NAME, ulMetaDataID3VersionOutput);
@@ -2424,60 +2512,61 @@
if(SUCCEEDED(retVal))
{
// Notify meta-editor about the flavor of meta-data it should process.
retVal = pOptions->SetPropertyULONG32(METADATAFLAVOR_OPTION_NAME, metaProcessorVars.InjectedMetaFlavors);
}
if(SUCCEEDED(retVal))
{
// Legacy ID32_BLOB property must not get in the way of newly defined properties.
// Tell file-writer to ignore it.
retVal = pOptions->SetPropertyULONG32(METADATAIGNORE_OPTION_NAME, METADATAIGNORE_ID32BLOB);
}
if(SUCCEEDED(retVal))
{
if(g_bUseDefaultMetaEditorProcessor)
{
retVal = pOptions->SetPropertyULONG32(BLASTMETADATA_OPTION_NAME, metaProcessorVars.ClearMetaData ? 1 : 0);
}
else
{
// Notify meta-editor that we do not want it to perform any default internal meta-data merging.
// Custom processor in this application performs special merging of extracted and injected meta-data.
retVal = pOptions->SetPropertyULONG32(BLASTMETADATA_OPTION_NAME, 1);
}
}
if(FAILED(retVal))
{
printf("Failed to initialize options.\n");
+ progRetCode = RC_ERROR_CANNOT_INIT_PROGRAM_OBJECT;
goto cleanup;
}
// display operation info
{
CHXString sStyles = MetaInfo::GetFlavorNames(metaProcessorVars.InjectedMetaFlavors);
if(!strOutputFileName.IsEmpty())
{
printf("Injecting %s style metadata: [%s] => [%s].\n\n",
sStyles.IsEmpty() ? "unspecified" : (const char*)sStyles,
(const char*)strInputFileName, (const char*)strOutputFileName);
}
else
{
printf("Extracting metadata from [%s].\n\n", (const char*)strInputFileName);
}
}
// start file processing
startTime = HX_GET_BETTERTICKCOUNT();
if(g_bUseDefaultMetaEditorProcessor)
{
printf("WARNING: Using default meta-data processor.\n"
"Some features will not work correctly: %s, %s, %s, %s.\n\n",
OPTION_STRING_KEYWORD_REMOVE, OPTION_STRING_KEYWORD_CLEAR,
OPTION_STRING_PICTURE_REMOVE, OPTION_STRING_PICTURE_CLEAR);
// read meta-info by using meta-editor's default meta-data processor
IHXValues* pExtractedMetaData = 0;
@@ -2530,157 +2619,176 @@
HX_RELEASE(pInjectedMetaData);
if(SUCCEEDED(retVal) && !g_bUseDTDriverSynchronousMode)
{
WaitAsyncDriveEnd();
retVal = pResponse->GetTerminationStatus();
}
}
}
else
{
// drive meta-info through meta-editor by using custom meta-data processor
if(SUCCEEDED(retVal))
{
retVal = pEditor->Drive((const char*)strInputFileName, (const char*)strOutputFileName,
(IHXMetaDataProcessor*)pProcessor,
pOptions, (IHXMetaDataEditorResponse*)pResponse);
if(SUCCEEDED(retVal) && !g_bUseDTDriverSynchronousMode)
{
WaitAsyncDriveEnd();
retVal = pResponse->GetTerminationStatus();
}
}
}
if(FAILED(retVal))
{
printf("Failed to process input file [%s].\n", (const char*)strInputFileName);
+ progRetCode = RC_ERROR_PROCESSING_MEDIA_FILE;
+ goto cleanup;
}
#ifdef HELIX_FEATURE_METAEDIT_AUDIO_HASH
if(metaProcessorVars.GenerateHash)
{
printf("--- Generated hash ---\n");
for (int i=0; i<32; i++)
{
printf("%x", metaProcessorVars.SHAHash[i]);
}
printf("\n");
}
#endif
// auto dump meta-data if extracting only
- if(strOutputFileName.IsEmpty())
+ if(strOutputFileName.IsEmpty() && !metaProcessorVars.GenerateHash)
{
bPrintMetaData = TRUE;
}
if(SUCCEEDED(retVal) && bPrintMetaData)
{
// dump extracted
printf("--- Extracted meta-data ---\n");
metaProcessorVars.ExtractedMetaInfo.Dump();
printf("\n");
// dump injected
if(!g_bUseDefaultMetaEditorProcessor && !strOutputFileName.IsEmpty())
{
printf("--- Injected meta-data ---\n");
metaProcessorVars.OutboundMetaInfo.Dump();
printf("\n");
}
}
// extract UITS data to file
if(SUCCEEDED(retVal) && !strUITSDataOutputFileName.IsEmpty())
{
EncodedString sUITSData;
if(SUCCEEDED(metaProcessorVars.ExtractedMetaInfo.GetStringItem(MetaInfo::StringMetaItem_UITSData, sUITSData))
&& !sUITSData.IsEmpty())
{
printf("--- Extracting UITSData to file ---\n");
printf("Saving UITSData to [%s].\n", (const char*)strUITSDataOutputFileName);
- if(!NeedOverwriteConfirmation((const char*)strUITSDataOutputFileName, bOverwriteFile))
+ if(NeedOverwriteConfirmation((const char*)strUITSDataOutputFileName, bOverwriteFile))
{
- if(FAILED(MetaInfo::SaveXMLStringToFile((const char*)strUITSDataOutputFileName, sUITSData)))
+ // report error but continue saving other data
+ progRetCode = RC_ERROR_OUTPUT_UITS_FILE_EXISTS;
+ }
+ else if(FAILED(MetaInfo::SaveXMLStringToFile((const char*)strUITSDataOutputFileName, sUITSData)))
{
+ // report error but continue saving other data
printf("Failed to save UITSData.\n");
- }
+ progRetCode = RC_ERROR_CANNOT_OUTPUT_UITS_FILE;
}
printf("\n");
}
}
// extract pictures to files
if(SUCCEEDED(retVal) && bExtractPicturesToFiles && metaProcessorVars.ExtractedMetaInfo.GetPictureCount())
{
printf("--- Extracting pictures to files ---\n");
for(UINT32 iPic = 0; iPic < metaProcessorVars.ExtractedMetaInfo.GetPictureCount(); iPic++)
{
ID3Tools::APICFrame* pFrame = metaProcessorVars.ExtractedMetaInfo.GetPictureByIndex(iPic);
if(pFrame)
{
CHXString filename = strPictureFileNamePrefix.IsEmpty() ? "picture" : strPictureFileNamePrefix;
filename.AppendULONG(iPic);
filename += "_type";
filename.AppendULONG(pFrame->GetPictureType());
if(pFrame->GetMimeType() == "image/jpeg")
{
filename += ".jpg";
}
else if(pFrame->GetMimeType() == "image/png")
{
filename += ".png";
}
else
{
filename += ".bin";
}
printf("Saving picture %d to [%s].\n", iPic, (const char*)filename);
- if(!NeedOverwriteConfirmation((const char*)filename, bOverwriteFile))
+ if(NeedOverwriteConfirmation((const char*)filename, bOverwriteFile))
+ {
+ // report error but continue saving other data
+ progRetCode = RC_ERROR_OUTPUT_PICTURE_FILE_EXISTS;
+ }
+ else
{
if(FAILED(pFrame->SavePictureDataToImageFile((const char*)filename)))
{
+ // report error but continue saving other data
printf("Failed to save picture %d.\n", iPic);
+ progRetCode = RC_ERROR_CANNOT_OUTPUT_PICTURE_FILE;
}
}
}
}
printf("\n");
}
if(SUCCEEDED(retVal))
{
UINT32 endTime = HX_GET_BETTERTICKCOUNT();
printf("Done. Processing time: %f seconds.\n", (endTime - startTime) / 1000.0);
}
// cleanup objects
cleanup:
HX_RELEASE(pEditor);
HX_RELEASE(pInputParser);
HX_RELEASE(pProcessor);
HX_RELEASE(pResponse);
HX_RELEASE(pOptions);
HX_RELEASE(pCommonClassFactory);
if(pMediaPlatform)
{
pMediaPlatform->Close();
}
HX_RELEASE(pMediaPlatform);
if(fpHXMediaPlatformClose)
{
fpHXMediaPlatformClose();
}
HX_DELETE(pDLLAccess);
- return retVal;
+ // if return value was not mapped to program return code, report generic error
+ if(FAILED(retVal) && (progRetCode == RC_SUCCESS))
+ {
+ progRetCode = RC_ERROR_GENERIC;
+ }
+
+ return progRetCode;
}