[Helix-client-dev] CR/CN: Windows-Unicode command line patches for GMPMetaEditor branch
Petar Basic <[email protected]> Fri, 15 Jan 2010 00:14:13 +0100
| Newsgroups | gmane.comp.multimedia.helix.devel |
|---|---|
| Message-ID | <[email protected]> |
Modified by: pbasic at real.com Date: 2010/01/14 Project: GMP MetaEditor (meta3gp.exe) Synopsis: Windows-Unicode command line patches for GMPMetaEditor branch Details: 1.) Adjusted string types and transfers in meta3gp project to make possible usage of Unicode command line on Windows. 2.) Fixed code-unit counting bugs in the following routines IsUTF8StringAsciiOnly, IsUTF16StringAsciiOnly, IsUTF32StringAsciiOnly. Testing: Verified operation on GMP MetaEditor on Windows XP SP2 and Solaris 5.10 Sparc via standard MetaEditor test scripts. Files Modified: common/util/uniconv.cpp datatype/tools/dtdriver/apps/meta3gp/HXXmlInputParser.cpp datatype/tools/dtdriver/apps/meta3gp/HXXmlInputParser.h 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
common_util.diff
(application/octet-stream, 5.3 KB)
Index: uniconv.cpp
===================================================================
RCS file: /cvsroot/common/util/uniconv.cpp,v
retrieving revision 1.2
diff -d -H -w -U30 -r1.2 uniconv.cpp
--- uniconv.cpp 28 Nov 2007 18:59:47 -0000 1.2
+++ uniconv.cpp 14 Jan 2010 22:49:25 -0000
@@ -55,154 +55,169 @@
// unicode constants
#define UNICODE_MAX_ASCII UINT32(0x0000007F)
#define UNICODE_HIGH_SURROGATE_START UINT32(0x0000D800)
#define UNICODE_HIGH_SURROGATE_END UINT32(0x0000DBFF)
#define UNICODE_LOW_SURROGATE_START UINT32(0x0000DC00)
#define UNICODE_LOW_SURROGATE_END UINT32(0x0000DFFF)
#define UNICODE_SURROGATE_BASE UINT32(0x00010000)
#define UNICODE_REPLACEMENT_CHAR UINT32(0x0000FFFD)
#define UNICODE_MAX_BMP UINT32(0x0000FFFF)
#define UNICODE_MAX_LEGAL UINT32(0x0010FFFF)
HXBOOL IsUTF8StringAsciiOnly(const UINT8* pCodeUnits, UINT32 uNumCodeUnits, UINT32& outNumUnits)
{
outNumUnits = 0;
if(!pCodeUnits)
{
return TRUE;
}
HXBOOL bUseInputLimit = (uNumCodeUnits != MAX_UINT32) ? TRUE : FALSE;
UINT32 remainingUnits = uNumCodeUnits;
while(TRUE)
{
if(bUseInputLimit && !remainingUnits)
{
break; //source exhausted
}
UINT8 codeUnit = *pCodeUnits++;
+ remainingUnits--;
+
if(codeUnit > UNICODE_MAX_ASCII)
{
return FALSE; //found non-ascii
}
+
outNumUnits++;
if(!bUseInputLimit && !codeUnit)
{
break; //found 0-terminator
}
}
return TRUE; //all units are ascii
}
HXBOOL IsUTF16StringAsciiOnly(const UINT16* pCodeUnits, UINT32 uNumCodeUnits,
HXBOOL bBigEndian, UINT32& outNumUnits)
{
outNumUnits = 0;
if(!pCodeUnits)
{
return TRUE;
}
HXBOOL bUseInputLimit = (uNumCodeUnits != MAX_UINT32) ? TRUE : FALSE;
UINT32 remainingUnits = uNumCodeUnits;
while(TRUE)
{
if(bUseInputLimit && !remainingUnits)
{
break; //source exhausted
}
- UINT16 codeUnit = *pCodeUnits++;
- const UINT8* pBytes = (const UINT8*)&codeUnit;
+ UINT16 codeUnit = *pCodeUnits;
+ const UINT8* pBytes = (const UINT8*)pCodeUnits;
+
+ pCodeUnits++;
+ remainingUnits--;
+
UINT8 bytes[2];
if(bBigEndian)
{
bytes[0] = pBytes[0];
bytes[1] = pBytes[1];
}
else
{
bytes[0] = pBytes[1];
bytes[1] = pBytes[0];
}
+
if((bytes[0] != 0) || (bytes[1] > UNICODE_MAX_ASCII))
{
return FALSE; //found non-ascii
}
+
outNumUnits++;
if(!bUseInputLimit && !codeUnit)
{
break; //found 0-terminator
}
}
return TRUE; //all units are ascii
}
HXBOOL IsUTF32StringAsciiOnly(const UINT32* pCodeUnits, UINT32 uNumCodeUnits,
HXBOOL bBigEndian, UINT32& outNumUnits)
{
outNumUnits = 0;
if(!pCodeUnits)
{
return TRUE;
}
HXBOOL bUseInputLimit = (uNumCodeUnits != MAX_UINT32) ? TRUE : FALSE;
- UINT32 remainingPoints = uNumCodeUnits;
+ UINT32 remainingUnits = uNumCodeUnits;
while(TRUE)
{
- if(bUseInputLimit && !remainingPoints)
+ if(bUseInputLimit && !remainingUnits)
{
break; //source exhausted
}
- UINT32 codeUnit = *pCodeUnits++;
- const UINT8* pBytes = (const UINT8*)&codeUnit;
+ UINT32 codeUnit = *pCodeUnits;
+ const UINT8* pBytes = (const UINT8*)pCodeUnits;
+
+ pCodeUnits++;
+ remainingUnits--;
+
UINT8 bytes[4];
if(bBigEndian)
{
bytes[0] = pBytes[0];
bytes[1] = pBytes[1];
bytes[2] = pBytes[2];
bytes[3] = pBytes[3];
}
else
{
bytes[0] = pBytes[3];
bytes[1] = pBytes[2];
bytes[2] = pBytes[1];
bytes[3] = pBytes[0];
}
+
if((bytes[0] != 0) || (bytes[1] != 0) || (bytes[2] != 0) || (bytes[3] > UNICODE_MAX_ASCII))
{
return FALSE; //found non-ascii
}
+
outNumUnits++;
if(!bUseInputLimit && !codeUnit)
{
break; //found 0-terminator
}
}
return TRUE; //all units are ascii
}
INT32 ConvertUTF8CodeUnitSequenceToUnicodeCodePoint(
UINT32& outCodePoint, UINT32& outNumConsumedCodeUnits,
const UINT8* pInCodeUnits, UINT32 uNumCodeUnits)
{
outCodePoint = 0; //set output to null-terminator for error cases
outNumConsumedCodeUnits = 0;
HXBOOL bUseUnitLimit = (uNumCodeUnits != MAX_UINT32) ? TRUE : FALSE;
if(!pInCodeUnits || (bUseUnitLimit && uNumCodeUnits < 1))
{
return -1; //not enough units
}
UINT32 codeUnitSeqLen = 1;
UINT32 codeUnit = UINT32(*pInCodeUnits);
// determine length of code-unit sequence
if(codeUnit >= UINT32(0x00) && codeUnit <= UNICODE_MAX_ASCII)
{
; //codeUnitSeqLen already set to 1
}
datatype_tools_dtdriver_apps_meta3gp.diff
(application/octet-stream, 55.6 KB)
Index: HXXmlInputParser.cpp
===================================================================
RCS file: /cvsroot/datatype/tools/dtdriver/apps/meta3gp/HXXmlInputParser.cpp,v
retrieving revision 1.2
diff -d -H -w -U30 -r1.2 HXXmlInputParser.cpp
--- HXXmlInputParser.cpp 6 Jan 2010 18:04:20 -0000 1.2
+++ HXXmlInputParser.cpp 14 Jan 2010 22:53:47 -0000
@@ -15,60 +15,61 @@
* applicable to this file, the RCSL. Please see the applicable RPSL or
* RCSL for the rights, obligations and limitations governing use of the
* contents of the file.
*
* This file is part of the Helix DNA Technology. RealNetworks is the
* developer of the Original Code and owns the copyrights in the portions
* it created.
*
* This file, and the files included with this file, is distributed and made
* available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
*
* Technology Compatibility Kit Test Suite(s) Location:
* http://www.helixcommunity.org/content/tck
*
* Contributor(s):
*
* ***** END LICENSE BLOCK ***** */
/****************************************************************************
* Includes
*/
#include "hxcom.h"
#include "hxbuffer.h"
#include "hxvalues.h"
+#include "hlxosstr.h"
#include "HXXmlInputParser.h"
CHXXmlInputParser::CHXXmlInputParser()
: m_lRefCount(0),
m_pXMLParser(NULL),
m_pResults(NULL),
m_ParsingResult(HXR_OK)
{
}
CHXXmlInputParser::~CHXXmlInputParser()
{
HX_RELEASE(m_pXMLParser);
}
STDMETHODIMP_(ULONG32) CHXXmlInputParser::AddRef()
{
return InterlockedIncrement(&m_lRefCount);
}
STDMETHODIMP_(ULONG32) CHXXmlInputParser::Release()
{
if (InterlockedDecrement(&m_lRefCount) > 0)
{
return m_lRefCount;
}
delete this;
@@ -103,69 +104,70 @@
IHXValues* pAttributes,
UINT32 ulLineNumber,
UINT32 ulColumnNumber)
{
// add the name to the path
m_sCurrentElementPath += "/";
m_sCurrentElementPath += pName;
return HXR_OK;
}
STDMETHODIMP CHXXmlInputParser::HandleEndElement(
const char* pName,
UINT32 ulLineNumber,
UINT32 ulColumnNumber)
{
// remove name from path
CHXString sName(pName);
m_sCurrentElementPath = m_sCurrentElementPath.Left(m_sCurrentElementPath.GetLength() - sName.GetLength() -1);
return HXR_OK;
}
STDMETHODIMP CHXXmlInputParser::HandleCharacterData(
IHXBuffer* pBuffer,
UINT32 ulLineNumber,
UINT32 ulColumnNumber)
{
- // if path exists, the set its value
+ // With current parser implementation we will assume UTF8
+ EncodedString strValue((const char*)pBuffer->GetBuffer(), HX_TEXT_ENCODING_TYPE_UTF8);
- CHXString strValue(pBuffer->GetBuffer());
if (!strValue.IsEmpty())
{
+ // copy value for known paths
XmlPair* currentValue = m_pResults->GetAt(m_sCurrentElementPath);
if (currentValue!=NULL)
{
- currentValue->xmlValue = strValue;
+ currentValue->xmlValueUTF8 = strValue;
}
}
return HXR_OK;
}
STDMETHODIMP CHXXmlInputParser::HandleProcessingInstruction(
const char* pTarget,
IHXValues* pAttributes,
UINT32 ulLineNumber,
UINT32 ulColumnNumber)
{
return HXR_OK;
}
STDMETHODIMP CHXXmlInputParser::HandleUnparsedEntityDecl(
const char* pEntityName,
const char* pSystemID,
const char* pPublicID,
const char* pNotationName,
UINT32 ulLineNumber,
UINT32 ulColumnNumber)
{
return HXR_OK;
}
STDMETHODIMP CHXXmlInputParser::HandleNotationDecl(
const char* pNotationName,
Index: HXXmlInputParser.h
===================================================================
RCS file: /cvsroot/datatype/tools/dtdriver/apps/meta3gp/HXXmlInputParser.h,v
retrieving revision 1.1.2.1
diff -d -H -w -U30 -r1.1.2.1 HXXmlInputParser.h
--- HXXmlInputParser.h 11 Jan 2010 17:52:26 -0000 1.1.2.1
+++ HXXmlInputParser.h 14 Jan 2010 22:53:47 -0000
@@ -18,109 +18,113 @@
*
* This file is part of the Helix DNA Technology. RealNetworks is the
* developer of the Original Code and owns the copyrights in the portions
* it created.
*
* This file, and the files included with this file, is distributed and made
* available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
*
* Technology Compatibility Kit Test Suite(s) Location:
* http://www.helixcommunity.org/content/tck
*
* Contributor(s):
*
* ***** END LICENSE BLOCK ***** */
/****************************************************************************
* Includes
*/
#ifndef _HXXMLINPUTPARSER_H_
#define _HXXMLINPUTPARSER_H_
#include "hxcom.h"
#include "hxstring.h"
#include "hxxml.h"
#include "carray.h"
+#include "encstr.h"
struct XmlPair
{
- XmlPair(const CHXString& path, const CHXString& value)
+ XmlPair(const CHXString& path, const EncodedString& valueUTF8)
: xmlPath(path)
- , xmlValue(value)
+ , xmlValueUTF8(valueUTF8)
{
}
CHXString xmlPath;
- CHXString xmlValue;
+ EncodedString xmlValueUTF8;
};
class CParsedXmlPairs
{
public:
~CParsedXmlPairs()
{
for(int i = 0; i < xmlPairs.GetSize(); i++)
{
delete (XmlPair*)xmlPairs.GetAt(i);
}
}
void Add(XmlPair* pair)
{
xmlPairs.Add(pair);
}
XmlPair* GetAt(const CHXString& xmlPath)
{
for(int i = 0; i < xmlPairs.GetSize(); i++)
{
XmlPair *pair = (XmlPair*)xmlPairs.GetAt(i);
if (pair->xmlPath == xmlPath)
{
return pair;
}
}
return NULL;
}
void Dump()
{
for(int i = 0; i < xmlPairs.GetSize(); i++)
{
XmlPair *pair = (XmlPair*)xmlPairs.GetAt(i);
- printf(" Xml xpath %s contains value: %s\n", (const char*)pair->xmlPath, (const char*)pair->xmlValue);
+
+ printf("%s = [", (const char*)pair->xmlPath);
+ EncStrUtils::PrintTextUTF8(pair->xmlValueUTF8.GetData());
+ printf("].\n");
}
}
CHXPtrArray* GetAllPairs()
{
return &xmlPairs;
}
private:
CHXPtrArray xmlPairs;
};
/*
* CHXXmlInputParser class implements XML upgrade manifest parser.
*/
class CHXXmlInputParser :
public IHXXMLParserResponse
{
public:
/*
* Class constructor. Initializes a new instance of the CHXXmlInputParser class.
*/
CHXXmlInputParser();
/**************************************************************************
* IHXContextUser methods
**************************************************************************/
STDMETHOD(QueryInterface) (THIS_
REFIID riid,
void** ppvObj);
Index: main.cpp
===================================================================
RCS file: /cvsroot/datatype/tools/dtdriver/apps/meta3gp/main.cpp,v
retrieving revision 1.7.2.1
diff -d -H -w -U30 -r1.7.2.1 main.cpp
--- main.cpp 11 Jan 2010 17:52:26 -0000 1.7.2.1
+++ main.cpp 14 Jan 2010 22:53:51 -0000
@@ -48,127 +48,121 @@
#include "ffdriver.h"
#include "cstrmsrt.h"
#include "hxmemprb.h"
#include "hxtick.h"
#include "chxpckts.h"
#include "pckunpck.h"
#include "dllpath.h"
#include "filespecutils.h"
#include "metainfokeys.h"
#include "uniconv.h"
#include "proptools.h"
#include "dllacces.h"
#include "ihxmetaeditor.h"
#include "HXXmlInputParser.h"
#include "metautil.h"
#include "meta3gp.ver"
#ifdef HELIX_FEATURE_METAEDIT_AUDIO_HASH
#include "mycrypt.h"
#endif
/****************************************************************************
* Meta-data command line editor.
* Build-time configuration options.
*/
// uncomment to force usage of legacy strings on Windows
// (only relevant for command-line argument transfer)
-//#define FORCE_LEGACY_CHAR 1
+//#define FORCE_LEGACY_CHAR_COMMAND_LINE 1
// environment variable name
#define PLUGIN_PATH_ENV_VAR_NAME "META3GP_PLUGIN_PATH"
/****************************************************************************
* Component operational modes
*/
HXBOOL g_bUseDefaultMetaEditorProcessor = FALSE;
HXBOOL g_bUseDTDriverSynchronousMode = TRUE;
/****************************************************************************
* System character type macros
*/
-#ifdef USE_WIDE_CHAR
-#undef USE_WIDE_CHAR
+#ifdef USE_WIDE_CHAR_COMMAND_LINE
+#undef USE_WIDE_CHAR_COMMAND_LINE
#endif
-#if defined(_WINDOWS) && !defined(FORCE_LEGACY_CHAR)
-#define USE_WIDE_CHAR 1
+#if !defined(FORCE_LEGACY_CHAR_COMMAND_LINE) && defined(_WINDOWS)
+#define USE_WIDE_CHAR_COMMAND_LINE 1
#endif
#ifdef _T
#undef _T
#endif
#ifdef TCHAR
#undef TCHAR
#endif
#ifdef TMAIN
#undef TMAIN
#endif
-#ifdef USE_WIDE_CHAR
+#ifdef USE_WIDE_CHAR_COMMAND_LINE
#define _T(Val) L##Val
#define TCHAR wchar_t
#define TMAIN wmain
#define TCHXStringCtor(Val) CHXString((const char*)CCPFromWCharT(Val))
-#define TUTF8EncodedStringVar(VarName, Val) EncodedString VarName((const char*)::UTF8FromWCharT(Val), HX_TEXT_ENCODING_TYPE_UTF8)
#define TUTF8EncodedStringCtor(Val) EncodedString((const char*)::UTF8FromWCharT(Val), HX_TEXT_ENCODING_TYPE_UTF8)
-#define TUTF8EncodedStringCCPVar(VarName, Val) EncodedString VarName((const char*)::UTF8FromCCP(Val), HX_TEXT_ENCODING_TYPE_UTF8)
-#define TUTF8EncodedStringCCPCtor(Val) EncodedString((const char*)::UTF8FromCCP(Val), HX_TEXT_ENCODING_TYPE_UTF8)
-#else //USE_WIDE_CHAR
+#else
#define _T(Val) Val
#define TCHAR char
#define TMAIN main
#define TCHXStringCtor(Val) CHXString(Val)
-#define TUTF8EncodedStringVar(VarName, Val) EncodedString VarName((const char*)::UTF8FromCCP(Val), HX_TEXT_ENCODING_TYPE_UTF8)
#define TUTF8EncodedStringCtor(Val) EncodedString((const char*)::UTF8FromCCP(Val), HX_TEXT_ENCODING_TYPE_UTF8)
-#define TUTF8EncodedStringCCPVar(VarName, Val) EncodedString VarName((const char*)::UTF8FromCCP(Val), HX_TEXT_ENCODING_TYPE_UTF8)
-#define TUTF8EncodedStringCCPCtor(Val) EncodedString((const char*)::UTF8FromCCP(Val), HX_TEXT_ENCODING_TYPE_UTF8)
-#endif //USE_WIDE_CHAR
+#endif //USE_WIDE_CHAR_COMMAND_LINE
/****************************************************************************
* Build-time messages
*/
#ifdef _WINDOWS
-#ifdef USE_WIDE_CHAR
+#ifdef USE_WIDE_CHAR_COMMAND_LINE
# pragma message("Using wide-string command-line arguments")
#else
# pragma message("Using legacy-string command-line arguments")
#endif
#endif //_WINDOWS
/****************************************************************************
* DLLAccessPath Variable
*/
ENABLE_DLLACCESS_PATHS(g_Meta3GPAccessPath);
/****************************************************************************
* Defines
*/
#define PROGRAM_NAME_STRING "RealNetworks meta-data editor"
#define PROGRAM_COPYRIGHT_STRING "Copyright (c) RealNetworks 2010"
// input/output control
#ifdef _WINDOWS
#define OPTION_STRING_ASYNCMODE "dev-asyncmode"
#endif //_WINDOWS
#define OPTION_STRING_DEFMETAPROC "dev-defmetaproc"
#define OPTION_STRING_INPUTFILE "if"
#define OPTION_STRING_OUTPUTFILE "of"
#define OPTION_STRING_XMLINPUTFILE "xmlin"
#define OPTION_STRING_XMLOUTPUTFILE "xmlout"
@@ -397,61 +391,61 @@
OptionDesc* od = (OptionDesc*)descs.GetAt(i);
if(strArg == od->GetOptionString())
{
return od;
}
}
return NULL;
}
OptionDesc* GetOptionDescWithPath(CHXString& strArg) const
{
for(int i = 0; i < descs.GetSize(); i++)
{
OptionDesc* od = (OptionDesc*)descs.GetAt(i);
if(strArg == od->GetXPath())
{
return od;
}
}
return NULL;
}
void InitializeXmlPairs(CParsedXmlPairs *xmlPairs)
{
for(int i = 0; i < descs.GetSize(); i++)
{
OptionDesc* desc = (OptionDesc*)descs.GetAt(i);
CHXString xpath(desc->GetXPath());
if (!xpath.IsEmpty())
{
- xmlPairs->Add(new XmlPair(xpath, CHXString("")));
+ xmlPairs->Add(new XmlPair(xpath, EncodedString()));
}
}
}
private:
CHXPtrArray descs;
};
void DisplayUsage(const TCHAR* argv0, OptionRegistry& optionReg)
{
const char* pszDbg = "";
#if defined(DEBUG) || defined(_DEBUG)
pszDbg = ".debug";
#endif
CHXString exeName = CHXFileSpecUtils::GetCurrentApplication().GetName();
printf("\n--- %s ---\n %s\n Version %s%s\n\n",
PROGRAM_NAME_STRING, PROGRAM_COPYRIGHT_STRING, TARVER_STRING_VERSION, pszDbg);
printf("usage: %s [ -option [value]... ]...\n", (const char*)exeName);
printf("with options:\n");
optionReg.PrintColumns(2);
}
/****************************************************************************
* Asynchronous mode helpers
*/
void SignalAsyncDriveEnd()
@@ -636,74 +630,83 @@
{
delete (ID3Tools::APICFrame*)a[i];
}
a.RemoveAll();
}
// meta-data input params
HXBOOL ClearMetaData;
HXBOOL ClearKeywords;
HXBOOL ClearPictures;
HXBOOL GenerateHash;
UINT32 InjectedMetaFlavors;
MetaInfo InjectedMetaInfo;
CHXPtrArray AddedKeywords; //EncodedString pointers
CHXPtrArray RemovedKeywords; //EncodedString pointers
CHXPtrArray AddedPictures; //ID3Tools::APICFrame pointers
CHXPtrArray RemovedPictures; //Integers
// meta-data output storage
MetaInfo ExtractedMetaInfo;
MetaInfo OutboundMetaInfo;
#ifdef HELIX_FEATURE_METAEDIT_AUDIO_HASH
unsigned char SHAHash[32];
hash_state HashState;
#endif
};
struct InputOption
{
- InputOption(const CHXString& optionName, const CHXString& optionValue, const CHXString& xmlOptionValue)
+ InputOption(const CHXString& optionName, const EncodedString& optionValueUTF8, const EncodedString& xmlOptionValueUTF8)
: OptionName(optionName)
- , OptionValue(optionValue)
- , XmlOptionValue(xmlOptionValue)
+ , OptionValueUTF8(optionValueUTF8)
+ , XmlOptionValueUTF8(xmlOptionValueUTF8)
{
}
- ~InputOption()
+ // XML value has precedence over command-line value
+ const EncodedString& GetEffectiveOptionValueUTF8() const
{
+ return XmlOptionValueUTF8.IsEmpty() ? OptionValueUTF8 : XmlOptionValueUTF8;
+ }
+
+ // XML value has precedence over command-line value
+ CHXString GetEffectiveOptionValueCCP() const
+ {
+ const EncodedString& val = GetEffectiveOptionValueUTF8();
+ return CHXString((const char*)CCPFromUTF8(val.GetData()));
}
CHXString OptionName;
- CHXString OptionValue;
- CHXString XmlOptionValue;
+ EncodedString OptionValueUTF8;
+ EncodedString XmlOptionValueUTF8;
};
/****************************************************************************
* Param extractors
*/
enum eCommandLineProcessorPhase
{
CLPP_IndependentOptions = 0,
CLPP_DependentOptions,
CLPP_Done
};
class ArgVars
{
public:
ArgVars(int argc_, TCHAR* argv_[], OptionRegistry& optionReg_)
: argc(argc_)
, argv(argv_)
, argPosition(0)
, optionReg(optionReg_)
{ }
void ResetPosition(int pos = 1)
{
argPosition = pos;
}
HXBOOL ReachedEndPosition()
{
return (argPosition >= argc);
@@ -741,418 +744,410 @@
return 0;
}
const TCHAR* CurrentArg(UINT32 offset, HXBOOL bOptional = FALSE)
{
int argIndex = argPosition + (int)offset;
if(argIndex < argc)
{
const TCHAR* pVal = argv[argIndex];
if(pVal && !optionReg.IsOption(pVal))
{
return pVal;
}
}
if(!bOptional)
{
CHXString strOption = TCHXStringCtor(CurrentOption(TRUE));
printf("Missing argument for option: %s\n", (const char*)strOption);
}
return 0;
}
private:
int argc;
TCHAR** argv;
int argPosition;
OptionRegistry& optionReg;
};
-void ReportUnsupportedMetaStyleOptionA(const char* optionName)
-{
- printf("Option %s not supported in combination with specified metastyle(s)\n", optionName);
-}
-
-void ReportUnsupportedMetaStyleOptionT(const TCHAR* optionName)
-{
- CHXString strOptionName = TCHXStringCtor(optionName);
- ReportUnsupportedMetaStyleOptionA((const char*)strOptionName);
-}
-
-void ReportInvalidValueForOptionA(const char* optionName, const char* optionValue)
+void ReportUnsupportedMetaStyleOption(const char* optionName)
{
- printf("Invalid value for option %s: %s\n", optionName, optionValue);
+ printf("Option -%s not supported in combination with specified metastyle(s)\n", optionName);
}
-void ReportInvalidValueForOptionT(const TCHAR* optionName, const TCHAR* optionValue)
+void ReportInvalidValueForOption(const char* optionName, const EncodedString& optionValueUTF8)
{
- CHXString strOptionName = TCHXStringCtor(optionName);
- CHXString strOptionValue = TCHXStringCtor(optionValue);
- ReportInvalidValueForOptionA((const char*)strOptionName, (const char*)strOptionValue);
+ printf("Invalid value for option -%s: ", optionName);
+ EncStrUtils::PrintTextUTF8(optionValueUTF8.GetData());
+ printf("\n");
}
HX_RESULT ProcessStringOption(bool bSkipArgOnly, InputOption* option, MetaInfo& metainfo,
MetaInfo::eStringMetaItem itemName, UINT32 metaFlavorFlags)
{
- if (option->OptionValue.IsEmpty() && option->XmlOptionValue.IsEmpty())
+ if(option->OptionValueUTF8.IsEmpty() && option->XmlOptionValueUTF8.IsEmpty())
{
return HXR_PARSE_ERROR;
}
if(bSkipArgOnly)
{
return HXR_OK;
}
- if (option->XmlOptionValue.IsEmpty())
+ if(option->XmlOptionValueUTF8.IsEmpty())
{
if(MetaInfo::IsItemSupportedByAnyFlavor(itemName, metaFlavorFlags))
{
// options are being read from the command line
- TUTF8EncodedStringCCPVar(sVal, option->OptionValue);
+ EncodedString sVal = option->OptionValueUTF8;
if(MetaInfo::IsItemValueValidForFlavors(itemName, sVal, metaFlavorFlags) &&
SUCCEEDED(metainfo.SetStringItem(itemName, sVal)))
{
return HXR_OK;
}
- ReportInvalidValueForOptionA(option->OptionName, option->OptionValue);
+ ReportInvalidValueForOption(option->OptionName, option->OptionValueUTF8);
return HXR_PARSE_ERROR;
}
- ReportUnsupportedMetaStyleOptionA(option->OptionName);
+ ReportUnsupportedMetaStyleOption(option->OptionName);
return HXR_PARSE_ERROR;
}
else
{
// xml options override the command line, however, xml options can not be set using the flavor,
// so in this case, if the xml option has value which is not valid for flavor, we'll just ignore it.
if(!MetaInfo::IsItemSupportedByAnyFlavor(itemName, metaFlavorFlags))
{
return HXR_OK;
}
- TUTF8EncodedStringCCPVar(sVal, option->XmlOptionValue);
+ EncodedString sVal = option->XmlOptionValueUTF8;
if(!MetaInfo::IsItemValueValidForFlavors(itemName, sVal, metaFlavorFlags))
{
return HXR_OK;
}
else
{
if (SUCCEEDED(metainfo.SetStringItem(itemName, sVal)))
{
return HXR_OK;
}
}
- ReportInvalidValueForOptionA(option->OptionName, option->XmlOptionValue);
+ ReportInvalidValueForOption(option->OptionName, option->XmlOptionValueUTF8);
return HXR_PARSE_ERROR;
}
}
inline HX_RESULT ProcessDependentStringOption(eCommandLineProcessorPhase phase, InputOption* option,
MetaProcessorVars& mpVars, MetaInfo::eStringMetaItem itemName)
{
return ProcessStringOption((phase != CLPP_DependentOptions),
option, mpVars.InjectedMetaInfo, itemName, mpVars.InjectedMetaFlavors);
}
HX_RESULT ProcessUIntOption(bool bSkipArgOnly, InputOption* option, MetaInfo& metainfo,
MetaInfo::eUIntMetaItem itemName, UINT32 metaFlavorFlags)
{
- if (option->OptionValue.IsEmpty() && option->XmlOptionValue.IsEmpty())
+ if(option->OptionValueUTF8.IsEmpty() && option->XmlOptionValueUTF8.IsEmpty())
{
return HXR_PARSE_ERROR;
}
if(bSkipArgOnly)
{
return HXR_OK;
}
- if (option->XmlOptionValue.IsEmpty())
+ if(option->XmlOptionValueUTF8.IsEmpty())
{
if(MetaInfo::IsItemSupportedByAnyFlavor(itemName, metaFlavorFlags))
{
// options are being read from the command line
- TUTF8EncodedStringCCPVar(sVal, option->OptionValue);
+ EncodedString sVal = option->OptionValueUTF8;
UINT32 uVal = 0;
if(PropTools::ExtractUInt32(uVal, sVal))
{
if(MetaInfo::IsItemValueValidForFlavors(itemName, uVal, metaFlavorFlags) &&
SUCCEEDED(metainfo.SetUIntItem(itemName, uVal, TRUE)))
{
return HXR_OK;
}
}
- ReportInvalidValueForOptionA(option->OptionName, option->OptionValue);
+ ReportInvalidValueForOption(option->OptionName, option->OptionValueUTF8);
return HXR_PARSE_ERROR;
}
- ReportUnsupportedMetaStyleOptionA(option->OptionName);
+ ReportUnsupportedMetaStyleOption(option->OptionName);
return HXR_PARSE_ERROR;
}
else
{
// xml options override the command line, however, xml options can not be set using the flavor,
// so in this case, if the xml option has value which is not valid for flavor, we'll just ignore it.
if(!MetaInfo::IsItemSupportedByAnyFlavor(itemName, metaFlavorFlags))
{
return HXR_OK;
}
- TUTF8EncodedStringCCPVar(sVal, option->XmlOptionValue);
+ EncodedString sVal = option->XmlOptionValueUTF8;
UINT32 uVal = 0;
if(PropTools::ExtractUInt32(uVal, sVal))
{
if(!MetaInfo::IsItemValueValidForFlavors(itemName, uVal, metaFlavorFlags))
{
return HXR_OK;
}
else
{
if (SUCCEEDED(metainfo.SetUIntItem(itemName, uVal, TRUE)))
{
return HXR_OK;
}
}
}
- ReportInvalidValueForOptionA(option->OptionName, option->XmlOptionValue);
+ ReportInvalidValueForOption(option->OptionName, option->XmlOptionValueUTF8);
return HXR_PARSE_ERROR;
}
}
inline HX_RESULT ProcessDependentUIntOption(eCommandLineProcessorPhase phase, InputOption* option,
MetaProcessorVars& mpVars, MetaInfo::eUIntMetaItem itemName)
{
return ProcessUIntOption((phase != CLPP_DependentOptions),
option, mpVars.InjectedMetaInfo, itemName, mpVars.InjectedMetaFlavors);
}
HX_RESULT ProcessKeywordStringOption(bool bSkipArgOnly, InputOption* option,
CHXPtrArray& aKeywords, UINT32 metaFlavorFlags)
{
- if(option->OptionValue.IsEmpty())
+ if(option->OptionValueUTF8.IsEmpty())
{
return HXR_PARSE_ERROR;
}
if(bSkipArgOnly)
{
return HXR_OK;
}
if(MetaInfo::IsItemSupportedByAnyFlavor(MetaInfo::ArrayMetaItem_Keywords, metaFlavorFlags))
{
- EncodedString* pEncStr = new TUTF8EncodedStringCCPCtor(option->OptionValue);
+ EncodedString* pEncStr = new EncodedString(option->OptionValueUTF8);
if(pEncStr && MetaInfo::IsKeywordValidForFlavors(*pEncStr, metaFlavorFlags))
{
aKeywords.Add(pEncStr);
return HXR_OK;
}
delete pEncStr;
- ReportInvalidValueForOptionA(option->OptionName, option->OptionValue);
+ ReportInvalidValueForOption(option->OptionName, option->OptionValueUTF8);
return HXR_PARSE_ERROR;
}
- ReportUnsupportedMetaStyleOptionA(option->OptionName);
+ 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,
MetaInfo::eStringMetaItem itemName, UINT32 metaFlavorFlags)
{
- if(option->OptionValue.IsEmpty())
+ 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->OptionValue;
+ CHXString sFileName = option->GetEffectiveOptionValueCCP();
if(!sFileName.IsEmpty())
{
EncodedString sXML;
HX_RESULT retVal = MetaInfo::LoadXMLStringFromFile((const char*)sFileName, sXML);
if(SUCCEEDED(retVal) &&
MetaInfo::IsItemValueValidForFlavors(itemName, sXML, metaFlavorFlags) &&
SUCCEEDED(metainfo.SetStringItem(itemName, sXML)))
{
return HXR_OK;
}
}
- ReportInvalidValueForOptionA(option->OptionName, option->OptionValue);
+ ReportInvalidValueForOption(option->OptionName, option->OptionValueUTF8);
return HXR_PARSE_ERROR;
}
- ReportUnsupportedMetaStyleOptionA(option->OptionName);
+ ReportUnsupportedMetaStyleOption(option->OptionName);
return HXR_PARSE_ERROR;
}
HX_RESULT ProcessRemovePictureOption(bool bSkipArgOnly, InputOption* option,
CHXPtrArray& aRemovedPictureTypes, UINT32 metaFlavorFlags)
{
- if(option->OptionValue.IsEmpty())
+ if(option->OptionValueUTF8.IsEmpty())
{
return HXR_PARSE_ERROR;
}
if(bSkipArgOnly)
{
return HXR_OK;
}
if(MetaInfo::IsItemSupportedByAnyFlavor(MetaInfo::ArrayMetaItem_Pictures, metaFlavorFlags))
{
- TUTF8EncodedStringCCPVar(sVal, option->OptionValue);
+ EncodedString sVal = option->OptionValueUTF8;
UINT32 uVal = 0;
if(PropTools::ExtractUInt32(uVal, sVal) &&
MetaInfo::IsAPICPictureTypeValidForFlavors(uVal, metaFlavorFlags))
{
aRemovedPictureTypes.AddIfUnique((void*)uVal);
return HXR_OK;
}
- ReportInvalidValueForOptionA(option->OptionName, option->OptionValue);
+ ReportInvalidValueForOption(option->OptionName, option->OptionValueUTF8);
return HXR_PARSE_ERROR;
}
- ReportUnsupportedMetaStyleOptionA(option->OptionName);
+ ReportUnsupportedMetaStyleOption(option->OptionName);
return HXR_PARSE_ERROR;
}
HX_RESULT ProcessAddPictureOption(bool bSkipArgOnly, InputOption* option,
CHXPtrArray& aAddedAPICFrames, UINT32 metaFlavorFlags)
{
- if(option->OptionValue.IsEmpty())
+ 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)
{
return HXR_OUTOFMEMORY;
}
// process image file
HX_RESULT retVal = HXR_FAILED;
- CHXString sFileName = option->OptionValue;
+ CHXString sFileName = option->GetEffectiveOptionValueCCP();
if(!sFileName.IsEmpty())
{
// 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))
{
retVal = HXR_FAILED;
}
}
}
if(FAILED(retVal))
{
printf("Invalid image file for option %s: %s\n",
(const char*)option->OptionName, (const char*)sFileName);
}
// export frame
if(SUCCEEDED(retVal) && pFrame)
{
if(!aAddedAPICFrames.AddIfUnique(pFrame))
{
retVal = HXR_FAILED;
}
}
if(FAILED(retVal))
{
// cleanup
HX_DELETE(pFrame);
}
return retVal;
}
- ReportUnsupportedMetaStyleOptionA(option->OptionName);
+ ReportUnsupportedMetaStyleOption(option->OptionName);
return HXR_PARSE_ERROR;
}
-// Caller is responsible for result deallocation
-HX_RESULT CopyCCPStringOption(ArgVars& argVars, CHXString& sOut, HXBOOL bOptional = FALSE)
+HX_RESULT CopyOptionArgumentString(ArgVars& argVars, EncodedString& sOut, HXBOOL bOptional = FALSE)
{
- const TCHAR* pVal = argVars.CurrentArg(1, bOptional);
+ sOut.Clear();
- sOut = TCHXStringCtor(pVal);
+ const TCHAR* pVal = argVars.CurrentArg(1, bOptional);
+ if(!pVal && !bOptional)
+ {
+ return HXR_PARSE_ERROR;
+ }
+ sOut = TUTF8EncodedStringCtor(pVal);
argVars.MovePosition(1);
return HXR_OK;
}
-
HXBOOL NeedOverwriteConfirmation(const char* pFileName, HXBOOL bOverwriteFile)
{
HXBOOL bNeedConfirmation = FALSE;
if(pFileName)
{
if(CHXFileSpecUtils::FileExists(CHXFileSpecifier(pFileName)))
{
if(!bOverwriteFile)
{
bNeedConfirmation = TRUE;
printf("Output file [%s] already exists. Use -%s option to force overwrite.\n",
pFileName, OPTION_STRING_OVERWRITEFILE);
}
}
}
return bNeedConfirmation;
}
/****************************************************************************
* Meta-data processor
*/
class CProcessor : public IHXMetaDataProcessor
{
public:
CProcessor(MetaProcessorVars& vars)
: m_lRefCount(0)
, m_vars(vars)
, m_pContext(0)
{
@@ -1373,181 +1368,187 @@
{
for(int i = 0; i < options.GetSize(); i++)
{
InputOption* option = (InputOption*)options.GetAt(i);
if (option->OptionName == optionName)
{
return option;
}
}
return 0;
}
// Returns pointer to option
InputOption* CurrentOption() const
{
if(position < options.GetSize())
{
return (InputOption*)options.GetAt(position);
}
return 0;
}
private:
CHXPtrArray options;
int position;
};
-HX_RESULT ParseCCPInputOptions(ArgVars& argVars, OptionRegistry& optionReg, InputOptions& inputOptions)
+HX_RESULT ParseCommandLineInputOptions(ArgVars& argVars, OptionRegistry& optionReg, InputOptions& inputOptions)
{
HX_RESULT retVal = HXR_OK;
for(argVars.ResetPosition(1); SUCCEEDED(retVal) && !argVars.ReachedEndPosition(); argVars.MovePosition(1))
{
// accept option format only
CHXString strOption = TCHXStringCtor(argVars.CurrentOption(FALSE));
if(strOption.IsEmpty())
{
printf("Found non-option command-line argument: %s\n",
(const char*)TCHXStringCtor(argVars.CurrentRawArg()));
retVal = HXR_PARSE_ERROR;
continue;
}
- // if option exists within options (optionRegs) in argVars
+ // check if we're looking at known option
OptionDesc* od = optionReg.GetOptionDesc(strOption);
if (od == NULL)
{
printf("Unrecognized option: -%s\n", (const char*)strOption);
retVal = HXR_PARSE_ERROR;
continue;
}
+ EncodedString optionArgument;
+
// get the option value and store it into inputOptions
- if (od->GetNumberOfOptions() == 0)
- {
- // no parameters
- inputOptions.Add(new InputOption(strOption, CHXString(""), CHXString("")));
- }
- else
+ switch(od->GetNumberOfOptions())
{
- CHXString optionArgument("");
- if (od->GetNumberOfOptions() == -1)
+ case -1:
{
// zero or one parameter
- retVal = CopyCCPStringOption(argVars, optionArgument, TRUE);
+ retVal = CopyOptionArgumentString(argVars, optionArgument, TRUE);
+ break;
}
- else if (od->GetNumberOfOptions() == 1)
+
+ case 0:
+ // no parameters
+ break;
+
+ case 1:
{
// one parameter
- retVal = CopyCCPStringOption(argVars, optionArgument);
+ retVal = CopyOptionArgumentString(argVars, optionArgument, FALSE);
+ break;
}
- inputOptions.Add(new InputOption(strOption, optionArgument, CHXString("")));
+
+ default:
+ // unsupported number of option arguments
+ retVal = HXR_PARSE_ERROR;
+ break;
}
+ if(SUCCEEDED(retVal))
+ {
+ inputOptions.Add(new InputOption(strOption, optionArgument, EncodedString()));
+ }
}
return retVal;
}
HX_RESULT ParseXMLInputOptions(IHXCommonClassFactory* pCommonClassFactory, CHXXmlInputParser* pInputParser,
InputOption* option, CParsedXmlPairs* parsedXmlResults)
{
- if(option->OptionValue.IsEmpty())
+ if(option->OptionValueUTF8.IsEmpty())
{
return HXR_FAIL;
}
- FILE* fp = fopen(option->OptionValue, "r");
+ FILE* fp = fopen((const char*)option->GetEffectiveOptionValueCCP(), "r");
if(fp == NULL)
{
- printf("Unable to open file: %s\n", (const char*)option->OptionValue);
+ printf("Unable to open file: %s\n", (const char*)option->GetEffectiveOptionValueCCP());
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;
retVal = pInputParser->Parse(pBuffer, bIsFinal);
if(!SUCCEEDED(retVal))
{
break;
}
}
if(nItemsRead < uParserBufferSize)
{
break;
}
}
}
}
if (SUCCEEDED(retVal))
{
// retrieve manifest
retVal = pInputParser->EndParse();
}
- if (SUCCEEDED(retVal))
- {
- parsedXmlResults->Dump();
- }
-
fclose(fp);
return retVal;
}
/****************************************************************************
* Main entry point
*/
int TMAIN(int argc, TCHAR* argv[])
{
// separate shell command from output
printf("\n");
// initialize variables
CHXFileSpecifier exeFileSpec;
UINT32 startTime = 0;
DLLAccess* pDLLAccess = 0;
FPHXMEDIAPLATFORMOPEN fpHXMediaPlatformOpen = 0;
FPHXCREATEMEDIAPLATFORM fpHXCreateMediaPlatform = 0;
FPHXMEDIAPLATFORMCLOSE fpHXMediaPlatformClose = 0;
IHXMediaPlatform* pMediaPlatform = 0;
IHXCommonClassFactory* pCommonClassFactory = 0;
IHXMetaDataEditor* pEditor = 0;
CResponse* pResponse = 0;
CProcessor* pProcessor = 0;
IHXValues* pOptions = 0;
char pDllPath[_MAX_PATH] = {0};
@@ -1765,181 +1766,191 @@
optionReg.Add(new OptionDesc(OPTION_STRING_DISKNUMBER, "<integer>", "update iTunes disc number", 1, "/albums/album/track/discNumber"));
optionReg.Add(new OptionDesc(OPTION_STRING_DISKSTOTAL, "<integer>", "update iTunes disc count", 1, "/albums/album/discCount"));
optionReg.Add(new OptionDesc());
optionReg.Add(new OptionDesc(OPTION_STRING_RATING_ENTITY, "<4 character code>", "update 3GPP rating entity", 1));
optionReg.Add(new OptionDesc(OPTION_STRING_RATING_CRITERIA, "<4 character code>", "update 3GPP rating criteria", 1));
optionReg.Add(new OptionDesc(OPTION_STRING_RATING_INFO, "<string>", "update 3GPP rating info", 1));
optionReg.Add(new OptionDesc(OPTION_STRING_CLASSIFICATION_ENTITY, "<4 character code>", "update 3GPP classification entity", 1));
optionReg.Add(new OptionDesc(OPTION_STRING_CLASSIFICATION_TABLE, "<integer 0..65535>", "update 3GPP classification table", 1));
optionReg.Add(new OptionDesc(OPTION_STRING_CLASSIFICATION_INFO, "<string>", "update 3GPP classification info", 1));
optionReg.Add(new OptionDesc(OPTION_STRING_KEYWORD_ADD, "<string>", "add 3GPP keyword", 1));
optionReg.Add(new OptionDesc(OPTION_STRING_KEYWORD_REMOVE, "<string>", "remove 3GPP keyword", 1));
optionReg.Add(new OptionDesc(OPTION_STRING_KEYWORD_CLEAR, 0, "clear all extracted 3GPP keywords", 0));
optionReg.Add(new OptionDesc(OPTION_STRING_LOCATION_NAME, "<string>", "update 3GPP location name", 1));
optionReg.Add(new OptionDesc(OPTION_STRING_LOCATION_ASTRONOMICAL_BODY, "<string>", "update 3GPP location astronomical body", 1));
optionReg.Add(new OptionDesc(OPTION_STRING_LOCATION_ADDITIONAL_NOTES, "<string>", "update 3GPP location notes", 1));
optionReg.Add(new OptionDesc(OPTION_STRING_LOCATION_ROLE, "<integer 0..255>", "update 3GPP location role", 1));
optionReg.Add(new OptionDesc(OPTION_STRING_LOCATION_LONGITUDE, "<decimal number>", "update 3GPP location longitude", 1));
optionReg.Add(new OptionDesc(OPTION_STRING_LOCATION_LATITUDE, "<decimal number>", "update 3GPP location latitude", 1));
optionReg.Add(new OptionDesc(OPTION_STRING_LOCATION_ALTITUDE, "<decimal number>", "update 3GPP location altitude", 1));
optionReg.Add(new OptionDesc(OPTION_STRING_LANGUAGE_CODE, "<3 character code>", "ISO639.2/T language code of 3GPP metadata text", 1));
optionReg.Add(new OptionDesc());
#ifdef _WINDOWS
optionReg.Add(new OptionDesc(OPTION_STRING_ASYNCMODE, 0, "dtdriver async mode (developer option)", 0));
#endif //_WINDOWS
optionReg.Add(new OptionDesc(OPTION_STRING_DEFMETAPROC, 0, "default meta processor (developer option)", 0));
optionReg.Add(new OptionDesc(OPTION_STRING_HELP, 0, "display help text", 0));
{
- // parse command line parameters
+ // parse command line
ArgVars argVars(argc, argv, optionReg);
- retVal = ParseCCPInputOptions(argVars, optionReg, inputOptions);
+ retVal = ParseCommandLineInputOptions(argVars, optionReg, inputOptions);
if (SUCCEEDED(retVal))
{
InputOption* optionXmlIn = inputOptions.GetOption(CHXString(OPTION_STRING_XMLINPUTFILE));
- if (optionXmlIn && !optionXmlIn->OptionValue.IsEmpty())
+ if(optionXmlIn && !optionXmlIn->OptionValueUTF8.IsEmpty())
{
// parse xml input file
+ if(SUCCEEDED(retVal))
+ {
+ printf("Processing XML input file:\n");
+ }
+
CParsedXmlPairs parsedXmlResults;
optionReg.InitializeXmlPairs(&parsedXmlResults);
retVal = ParseXMLInputOptions(pCommonClassFactory, pInputParser, optionXmlIn, &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);
- if (optDesc!=NULL && !pair->xmlValue.IsEmpty()) // we'll add them only if there exist not null element in results of parsing xml
+ // 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, CHXString(""), pair->xmlValue));
+ inputOptions.Add(new InputOption(strName, EncodedString(), pair->xmlValueUTF8));
}
else
{
- printf("Xml parameter is overriding input parameter: %s.\n",(const char *)strName );
- inOpt->XmlOptionValue = pair->xmlValue;
+ 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");
}
}
}
}
-
// The first phase seeks for independent arguments, the second phase seeks for dependent arguments.
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;
- CHXString strOptionValue = option->XmlOptionValue.IsEmpty()? option->OptionValue : option->XmlOptionValue;
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;
}
else if(strOption == OPTION_STRING_INPUTFILE)
{
- strInputFileName = strOptionValue;
+ strInputFileName = option->GetEffectiveOptionValueCCP();
}
else if(strOption == OPTION_STRING_OUTPUTFILE)
{
- strOutputFileName = strOptionValue;
+ strOutputFileName = option->GetEffectiveOptionValueCCP();
}
else if(strOption == OPTION_STRING_OVERWRITEFILE)
{
bOverwriteFile = TRUE;
}
else if(strOption == OPTION_STRING_CLEARMETADATA)
{
metaProcessorVars.ClearMetaData = TRUE;
}
else if(strOption == OPTION_STRING_PRINTMETADATA)
{
bPrintMetaData = TRUE;
}
else if(strOption == OPTION_STRING_GENERATEHASH)
{
metaProcessorVars.GenerateHash = TRUE;
}
else if(strOption == OPTION_STRING_XMLINPUTFILE)
{
// do nothing, since it was already done what needs to be done
}
else if(strOption == OPTION_STRING_METASTYLE)
{
- strMetaStyleName = strOptionValue;
+ 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;
- ReportInvalidValueForOptionA(OPTION_STRING_METASTYLE, (const char*)strMetaStyleName);
+ 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);
}
@@ -1968,78 +1979,78 @@
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),
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))
{
- ReportUnsupportedMetaStyleOptionA(OPTION_STRING_PICTURE_CLEAR);
+ ReportUnsupportedMetaStyleOption(OPTION_STRING_PICTURE_CLEAR);
retVal = HXR_PARSE_ERROR;
}
}
else if(strOption == OPTION_STRING_PICTURE_EXTRACT)
{
bExtractPicturesToFiles = TRUE;
- strPictureFileNamePrefix = strOptionValue;
+ strPictureFileNamePrefix = option->GetEffectiveOptionValueCCP();
}
else if(strOption == OPTION_STRING_UITS_INSERT)
{
retVal = ProcessXMLFileStringOption((clpp != CLPP_DependentOptions),
option, metaProcessorVars.InjectedMetaInfo, MetaInfo::StringMetaItem_UITSData,
metaProcessorVars.InjectedMetaFlavors);
}
else if(strOption == OPTION_STRING_UITS_EXTRACT)
{
- strUITSDataOutputFileName = strOptionValue;
+ 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,
metaProcessorVars, MetaInfo::StringMetaItem_Lyrics);
}
else if(strOption == OPTION_STRING_SUBTITLE)
{
retVal = ProcessDependentStringOption(clpp, option,
metaProcessorVars, MetaInfo::StringMetaItem_TrackSubtitle);
@@ -2134,61 +2145,61 @@
retVal = ProcessDependentStringOption(clpp, option,
metaProcessorVars, MetaInfo::StringMetaItem_LocationLongitude);
}
else if(strOption == OPTION_STRING_LOCATION_LATITUDE)
{
retVal = ProcessDependentStringOption(clpp, option,
metaProcessorVars, MetaInfo::StringMetaItem_LocationLatitude);
}
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))
{
- ReportUnsupportedMetaStyleOptionA(OPTION_STRING_KEYWORD_CLEAR);
+ ReportUnsupportedMetaStyleOption(OPTION_STRING_KEYWORD_CLEAR);
retVal = HXR_PARSE_ERROR;
}
}
else
{
printf("Unrecognized option: -%s\n", (const char*)strOption);
retVal = HXR_PARSE_ERROR;
}
}
// 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"))
{