[Helix-client-dev] CR/CN: Accepting UTF8 command line arguments instead of wide chars. [GMPMetaEditor branch]
Petar Basic <[email protected]> Wed, 20 Jan 2010 20:18:01 +0100
| Newsgroups | gmane.comp.multimedia.helix.devel |
|---|---|
| Message-ID | <[email protected]> |
Modified by: pbasic at real.com Date: 2010/01/20 Project: GMPMetaEditor (meta3gp.exe) Synopsis: Accepting UTF8 command line arguments instead of wide chars. [GMPMetaEditor branch] Details: Although wide character program arguments are passed correctly from the Windows console, this is not the case when the program gets called from a batch script or from a WSH script. To be able to pass international characters to the program, -utf8in program option has been implemented instead of using wmain main entry prototype. -utf8in tells the program to treat command line arguments as UTF8 formatted strings. Tested on Windows and Solaris from console and from batch scripts. 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, 34.3 KB)
Index: main.cpp
===================================================================
RCS file: /cvsroot/datatype/tools/dtdriver/apps/meta3gp/main.cpp,v
retrieving revision 1.7.2.5
diff -d -H -w -U30 -r1.7.2.5 main.cpp
--- main.cpp 18 Jan 2010 21:34:33 -0000 1.7.2.5
+++ main.cpp 20 Jan 2010 19:11:04 -0000
@@ -46,157 +46,98 @@
#include "hxtypes.h"
#include "hlxosstr.h"
#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_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_COMMAND_LINE
-#undef USE_WIDE_CHAR_COMMAND_LINE
-#endif
-
-#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_COMMAND_LINE
-
-#define _T(Val) L##Val
-#define TCHAR wchar_t
-#define TMAIN wmain
-#define TCHXStringCtor(Val) CHXString((const char*)CCPFromWCharT(Val))
-#define TUTF8EncodedStringCtor(Val) EncodedString((const char*)::UTF8FromWCharT(Val), HX_TEXT_ENCODING_TYPE_UTF8)
-
-#else
-
-#define _T(Val) Val
-#define TCHAR char
-#define TMAIN main
-#define TCHXStringCtor(Val) CHXString(Val)
-#define TUTF8EncodedStringCtor(Val) EncodedString((const char*)::UTF8FromCCP(Val), HX_TEXT_ENCODING_TYPE_UTF8)
-
-#endif //USE_WIDE_CHAR_COMMAND_LINE
-
-
-/****************************************************************************
- * Build-time messages
- */
-#ifdef _WINDOWS
-
-#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_VENDOR_STRING "RealNetworks"
#define PROGRAM_NAME_STRING PROGRAM_VENDOR_STRING" meta-data editor"
#define PROGRAM_COPYRIGHT_STRING "Copyright (c) "PROGRAM_VENDOR_STRING" 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"
#define OPTION_STRING_CLEARMETADATA "metaclear"
#define OPTION_STRING_METASTYLE "metastyle"
-#define OPTION_STRING_UTF16OUTPUT "utf16"
+#define OPTION_STRING_UTF16OUTPUT "utf16out"
+#define OPTION_STRING_UTF8INPUT "utf8in"
#define OPTION_STRING_ID3V240OUTPUT "id3v240"
#define OPTION_STRING_ID3V230OUTPUT "id3v230"
#define OPTION_STRING_ID3V2NOOUTPUT "id3v2no"
#define OPTION_STRING_OVERWRITEFILE "overwrite"
#define OPTION_STRING_PRINTMETADATA "print"
#define OPTION_STRING_HELP "help"
#define OPTION_STRING_GENERATEHASH "audiohash"
#define OPTION_STRING_LOGFILE "log"
// common metadata
#define OPTION_STRING_TITLE "title"
#define OPTION_STRING_ARTIST "artist"
#define OPTION_STRING_ALBUM "album"
#define OPTION_STRING_GENRE "genre"
#define OPTION_STRING_COMPOSER "composer"
#define OPTION_STRING_COMMENT "comment"
#define OPTION_STRING_TRACKNUMBER "track"
#define OPTION_STRING_YEAR "year"
#define OPTION_STRING_PICTURE_ADD "addpic"
#define OPTION_STRING_PICTURE_REMOVE "rempic"
#define OPTION_STRING_PICTURE_CLEAR "clrpic"
#define OPTION_STRING_PICTURE_EXTRACT "savepic"
#define OPTION_STRING_UITS_INSERT "insertsignature"
#define OPTION_STRING_UITS_EXTRACT "extractsignature"
// iTunes specific metadata
#define OPTION_STRING_SOFTWARE "software"
#define OPTION_STRING_ENCODEDBY "encodedby"
@@ -415,73 +356,73 @@
{
int leftColumnWidth = 0;
for(int i = 0; i < descs.GetSize(); i++)
{
OptionDesc* od = (OptionDesc*)descs.GetAt(i);
int width = od->GetLeftColumnWidth();
if(width > leftColumnWidth)
{
leftColumnWidth = width;
}
}
return leftColumnWidth;
}
void PrintColumns(int columnSpacing = 1)
{
int leftColumnWidth = CalcLeftColumnWidth() + columnSpacing;
for(int i = 0; i < descs.GetSize(); i++)
{
OptionDesc* od = (OptionDesc*)descs.GetAt(i);
CHXString line = od->BuildLine(leftColumnWidth);
if(!line.IsEmpty())
{
printf("%s\n", (const char*)line);
}
}
}
- HXBOOL IsOption(const TCHAR* pArg)
+ HXBOOL IsOption(const char* pArg)
{
if(!pArg)
{
return FALSE;
}
- if(pArg[0] != _T('-'))
+ if(pArg[0] != '-')
{
return FALSE;
}
- CHXString arg = TCHXStringCtor(pArg + 1);
+ CHXString arg(pArg + 1);
for(int i = 0; i < descs.GetSize(); i++)
{
OptionDesc* od = (OptionDesc*)descs.GetAt(i);
if(arg == od->GetOptionString())
{
return TRUE;
}
}
return FALSE;
}
OptionDesc* GetOptionDesc(CHXString& strArg) const
{
for(int i = 0; i < descs.GetSize(); i++)
{
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);
@@ -498,61 +439,61 @@
for(int i = 0; i < descs.GetSize(); i++)
{
OptionDesc* desc = (OptionDesc*)descs.GetAt(i);
for(int iPath = 0; iPath < desc->GetNumXPaths(); iPath++)
{
CHXString xpath = desc->GetXPath(iPath);
if(!xpath.IsEmpty())
{
xmlPathDescs.Add(new XmlPathDesc(xpath));
}
}
}
}
private:
CHXPtrArray descs;
};
void DisplayProgramInfo()
{
const char* pszDbg = "";
#if defined(DEBUG) || defined(_DEBUG)
pszDbg = ".debug";
#endif
printf("\n--- %s ---\n %s\n Version %s%s\n\n",
PROGRAM_NAME_STRING, PROGRAM_COPYRIGHT_STRING, TARVER_STRING_VERSION, pszDbg);
}
-void DisplayUsage(const TCHAR* argv0, OptionRegistry& optionReg)
+void DisplayUsage(const char* argv0, OptionRegistry& optionReg)
{
CHXString exeName = CHXFileSpecUtils::GetCurrentApplication().GetName();
printf("usage: %s [ -option [value]... ]...\n", (const char*)exeName);
printf("with options:\n");
optionReg.PrintColumns(2);
}
CHXString GetUTCTimeString()
{
time_t currTime = time(0);
tm* pUTCTime = gmtime(&currTime);
const UINT32 bufSize = 64;
char buffer[bufSize];
strftime(buffer, bufSize, "%Y-%m-%dT%H:%M:%SZ", pUTCTime);
return CHXString(buffer);
}
/****************************************************************************
* Asynchronous mode helpers
*/
void SignalAsyncDriveEnd()
{
#ifdef _WINDOWS
::PostMessage(0, (WM_USER + 202), 0, 0);
#else
@@ -773,145 +714,164 @@
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;
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_)
+ ArgVars(int argc_, char* argv_[], OptionRegistry& optionReg_)
: argc(argc_)
, argv(argv_)
, argPosition(0)
, optionReg(optionReg_)
{ }
void ResetPosition(int pos = 1)
{
argPosition = pos;
}
HXBOOL ReachedEndPosition()
{
return (argPosition >= argc);
}
void MovePosition(int step = 1)
{
argPosition += step;
if(argPosition < 0)
{
argPosition = 0;
}
}
- const TCHAR* CurrentRawArg()
+ const char* CurrentRawArg()
{
if(argPosition < argc)
{
return argv[argPosition];
}
return 0;
}
// Returns pointer to option name
- const TCHAR* CurrentOption(HXBOOL bWithPrefix)
+ const char* CurrentOption(HXBOOL bWithPrefix)
{
if(argPosition < argc)
{
- const TCHAR* pVal = argv[argPosition];
- if(pVal && (pVal[0] == _T('-')))
+ const char* pVal = argv[argPosition];
+ if(pVal && (pVal[0] == '-'))
{
return bWithPrefix ? pVal : (pVal + 1);
}
}
return 0;
}
- const TCHAR* CurrentArg(UINT32 offset, HXBOOL bOptional, HXBOOL bPrintError)
+ const char* CurrentArg(UINT32 offset, HXBOOL bOptional, HXBOOL bPrintError)
{
int argIndex = argPosition + (int)offset;
if(argIndex < argc)
{
- const TCHAR* pVal = argv[argIndex];
+ const char* pVal = argv[argIndex];
if(pVal && !optionReg.IsOption(pVal))
{
return pVal;
}
}
if(!bOptional && bPrintError)
{
- CHXString strOption = TCHXStringCtor(CurrentOption(TRUE));
- printf("Missing argument for option: %s\n", (const char*)strOption);
+ printf("Missing argument for option: %s\n", CurrentOption(TRUE));
}
return 0;
}
- void DumpCommandLine()
+ void DumpCommandLine(HXBOOL bInterpretAsUTF8)
{
+#ifdef _WINDOWS
+ printf(::GetCommandLineA());
+#else
for(int i = 0; i < argc; i++)
{
-#ifdef USE_WIDE_CHAR_COMMAND_LINE
- wprintf(L"%ls ", argv[i]);
-#else
+ HXBOOL bFoundWhitespace = 0;
+ if(strchr(argv[i], ' '))
+ {
+ bFoundWhitespace = TRUE;
+ printf("\"");
+ }
+
+ if(bInterpretAsUTF8)
+ {
+ EncStrUtils::PrintText(argv[i], HX_TEXT_ENCODING_TYPE_UTF8);
+ }
+ else
+ {
printf("%s ", argv[i]);
-#endif
}
+
+ if(bFoundWhitespace)
+ {
+ printf("\"");
+ }
+ printf(" ");
+ }
+#endif
printf("\n");
}
private:
int argc;
- TCHAR** argv;
+ char** argv;
int argPosition;
OptionRegistry& optionReg;
};
void ReportUnsupportedMetaStyleOption(const char* optionName)
{
printf("Option -%s not supported in combination with specified metastyle(s)\n", optionName);
}
void ReportInvalidValueForOption(const char* optionName, const EncodedString& optionValueUTF8)
{
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->OptionValueUTF8.IsEmpty() && option->XmlOptionValueUTF8.IsEmpty())
{
return HXR_PARSE_ERROR;
}
if(bSkipArgOnly)
{
return HXR_OK;
}
if(option->XmlOptionValueUTF8.IsEmpty())
@@ -1218,71 +1178,80 @@
}
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)
+HX_RESULT CopyOptionArgumentString(ArgVars& argVars, HXBOOL bInterpretAsUTF8,
+ EncodedString& sOut, HXBOOL bOptional)
{
sOut.Clear();
- const TCHAR* pVal = argVars.CurrentArg(1, bOptional, TRUE);
+ const char* pVal = argVars.CurrentArg(1, bOptional, TRUE);
if(!pVal)
{
return bOptional ? HXR_OK : HXR_PARSE_ERROR;
}
- sOut = TUTF8EncodedStringCtor(pVal);
+ if(bInterpretAsUTF8)
+ {
+ sOut.Set(pVal, HX_TEXT_ENCODING_TYPE_UTF8);
+ }
+ else
+ {
+ sOut.Set((const char*)::UTF8FromCCP(pVal), HX_TEXT_ENCODING_TYPE_UTF8);
+ }
+
argVars.MovePosition(1);
return HXR_OK;
}
class InputOptions
{
public:
InputOptions()
: position(0)
{
}
~InputOptions()
{
Clear();
}
void Clear()
{
for(int i = 0; i < options.GetSize(); i++)
{
delete (InputOption*)options.GetAt(i);
}
options.RemoveAll();
position = 0;
}
void Add(InputOption* inputOpt)
@@ -1339,120 +1308,119 @@
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 ParseCommandLineInputOptions(ArgVars& argVars, OptionRegistry& optionReg, InputOptions& inputOptions,
- HXBOOL bStrictMode, HXBOOL bPrintErrors)
+ HXBOOL bInterpretAsUTF8, HXBOOL bStrictMode, HXBOOL bPrintErrors)
{
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));
+ CHXString strOption(argVars.CurrentOption(FALSE));
if(strOption.IsEmpty())
{
if(bPrintErrors)
{
- printf("Found non-option command-line argument: %s\n",
- (const char*)TCHXStringCtor(argVars.CurrentRawArg()));
+ printf("Found non-option command-line argument: %s\n", argVars.CurrentRawArg());
}
if(bStrictMode)
{
retVal = HXR_PARSE_ERROR;
}
continue;
}
// check if we're looking at known option
OptionDesc* od = optionReg.GetOptionDesc(strOption);
if(od == NULL)
{
if(bPrintErrors)
{
printf("Unrecognized option: -%s\n", (const char*)strOption);
}
if(bStrictMode)
{
retVal = HXR_PARSE_ERROR;
}
continue;
}
EncodedString optionArgument;
// retrieve argument values and store them into inputOptions
UINT32 numArgs = od->GetNumberOfArguments();
switch(numArgs)
{
case -1:
{
// zero or one argument
numArgs = 1;
- retVal = CopyOptionArgumentString(argVars, optionArgument, TRUE);
+ retVal = CopyOptionArgumentString(argVars, bInterpretAsUTF8, optionArgument, TRUE);
break;
}
case 0:
// no arguments
break;
case 1:
{
// one argument
- retVal = CopyOptionArgumentString(argVars, optionArgument, FALSE);
+ retVal = CopyOptionArgumentString(argVars, bInterpretAsUTF8, 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,
const CHXString& strInputXMLFileName, CParsedXmlPairs& parsedXmlResults,
CXmlPathDescs& xmlPathDescs)
{
if(strInputXMLFileName.IsEmpty())
@@ -1747,115 +1715,117 @@
m_bHashGenerated = FALSE;
}
#endif
return HXR_OK;
}
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[])
+int main(int argc, char* argv[])
{
// initialize variables
HX_RESULT retVal = HXR_OK;
int progRetCode = RC_SUCCESS;
UINT32 startTime = 0;
CHXFileSpecifier exeFileSpec;
HXBOOL bUsingLog = 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 strOutputXMLFileName;
CHXString strPictureFileNamePrefix;
CHXString strUITSDataOutputFileName;
CHXString strMetaStyleName;
HXBOOL bDisplayHelp = FALSE;
HXBOOL bOverwriteFile = FALSE;
HXBOOL bPrintMetaData = FALSE;
HXBOOL bExtractPicturesToFiles = FALSE;
HXBOOL bUTF16Output = FALSE;
+ HXBOOL bUTF8Input = FALSE;
UINT32 ulMetaDataID3VersionOutput = METADATAID3VERSION_240;
MetaProcessorVars metaProcessorVars;
// construct option registry
OptionRegistry optionReg;
optionReg.Add(new OptionDesc(OPTION_STRING_LOGFILE, "<filename>", "redirect console output to log file", 1));
optionReg.Add(new OptionDesc(OPTION_STRING_INPUTFILE, "<filename>", "input file", 1, "/albums/album/track/mediaFile/fileName"));
optionReg.Add(new OptionDesc(OPTION_STRING_OUTPUTFILE, "<filename>", "output file", 1, "/albums/album/track/outputFileName"));
optionReg.Add(new OptionDesc(OPTION_STRING_XMLINPUTFILE, "<filename>", "XML file with input parameters", 1));
optionReg.Add(new OptionDesc(OPTION_STRING_XMLOUTPUTFILE, "<filename>", "metadata output XML file", 1));
optionReg.Add(new OptionDesc(OPTION_STRING_OVERWRITEFILE, 0, "overwrite output file if it exists", 0));
optionReg.Add(new OptionDesc(OPTION_STRING_CLEARMETADATA, 0, "clear all extracted metadata before injection", 0));
optionReg.Add(new OptionDesc(OPTION_STRING_METASTYLE, "<3GPP | iTunes>", "flavor of injected metadata", 1));
- optionReg.Add(new OptionDesc(OPTION_STRING_UTF16OUTPUT, 0, "inject metadata strings in UTF16 format", 0));
+ optionReg.Add(new OptionDesc(OPTION_STRING_UTF16OUTPUT, 0, "use UTF16 format to store strings in output file", 0));
+ optionReg.Add(new OptionDesc(OPTION_STRING_UTF8INPUT, 0, "parse command line as UTF8 strings", 0));
optionReg.Add(new OptionDesc(OPTION_STRING_ID3V240OUTPUT, 0, "inject ID3v2 version 2.4.0, default", 0));
optionReg.Add(new OptionDesc(OPTION_STRING_ID3V230OUTPUT, 0, "inject ID3v2 version 2.3.0", 0));
optionReg.Add(new OptionDesc(OPTION_STRING_ID3V2NOOUTPUT, 0, "skip injecting ID3v2 tag", 0));
optionReg.Add(new OptionDesc(OPTION_STRING_PRINTMETADATA, 0, "print updated metadata", 0));
optionReg.Add(new OptionDesc(OPTION_STRING_PICTURE_EXTRACT, "[filename prefix]", "save extracted pictures", -1));
optionReg.Add(new OptionDesc(OPTION_STRING_GENERATEHASH, 0, "generate hash", 0));
optionReg.Add(new OptionDesc());
optionReg.Add(new OptionDesc(OPTION_STRING_TITLE, "<string>", "update title", 1, "/albums/album/track/name"));
optionReg.Add(new OptionDesc(OPTION_STRING_ARTIST, "<string>", "update 3GPP performer, iTunes artist", 1, "/albums/album/track/artist/name"));
optionReg.Add(new OptionDesc(OPTION_STRING_ALBUM, "<string>", "update album", 1, "/albums/album/name"));
optionReg.Add(new OptionDesc(OPTION_STRING_GENRE, "<string>", "update genre", 1, "/albums/album/track/style/name"));
optionReg.Add(new OptionDesc(OPTION_STRING_COMPOSER, "<string>", "update 3GPP author, iTunes composer", 1, "/albums/album/track/artist/composer"));
optionReg.Add(new OptionDesc(OPTION_STRING_COMMENT, "<string>", "update 3GPP description, iTunes comment", 1, "/albums/album/pline"));
optionReg.Add(new OptionDesc(OPTION_STRING_COPYRIGHT, "<string>", "update copyright", 1, "/albums/album/cline"));
optionReg.Add(new OptionDesc(OPTION_STRING_TRACKNUMBER, "<integer 0..255>", "update track number", 1, "/albums/album/track/sequence"));
optionReg.Add(new OptionDesc(OPTION_STRING_YEAR, "<integer 0..65536>", "update 3GPP recording year, iTunes release date", 1, "/albums/album/OrigReleaseYear"));
{
// Add picture
CHXPtrArray* pPictureAddXPaths = new CHXPtrArray;
pPictureAddXPaths->Add(new CHXString("/albums/album/image/fileName"));
pPictureAddXPaths->Add(new CHXString("/albums/album/image/fileName2"));
optionReg.Add(new OptionDesc(OPTION_STRING_PICTURE_ADD, "<filename>", "add picture", 1, 0, pPictureAddXPaths));
}
optionReg.Add(new OptionDesc(OPTION_STRING_PICTURE_REMOVE, "<APIC picture type>", "remove picture", 1));
optionReg.Add(new OptionDesc(OPTION_STRING_PICTURE_CLEAR, 0, "clear all extracted pictures", 0));
optionReg.Add(new OptionDesc(OPTION_STRING_UITS_INSERT, "<filename>", "insert UITS signature from file", 1));
optionReg.Add(new OptionDesc(OPTION_STRING_UITS_EXTRACT, "<filename>", "extract UITS signature into file", 1));
optionReg.Add(new OptionDesc());
optionReg.Add(new OptionDesc(OPTION_STRING_SOFTWARE, "<string>", "update iTunes generator tool", 1));
@@ -1874,109 +1844,115 @@
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 asynchronous 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 the command line
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);
+ // scan for utf8in and log options, but do not print syntax errors yet
+ retVal = ParseCommandLineInputOptions(argVars, optionReg, inputOptions, FALSE, FALSE, FALSE);
+
+ // scan for UTF8 input option before rescan
+ if(inputOptions.GetOption(OPTION_STRING_UTF8INPUT))
+ {
+ bUTF8Input = TRUE;
+ }
// 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
{
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();
+ argVars.DumpCommandLine(bUTF8Input);
}
// 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);
+ // parse the command line again with correct encoding, this time print errors
+ retVal = ParseCommandLineInputOptions(argVars, optionReg, inputOptions, bUTF8Input, TRUE, TRUE);
// 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);
@@ -2282,60 +2258,64 @@
}
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_UTF8INPUT)
+ {
+ bUTF8Input = 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);
}
else if(strOption == OPTION_STRING_ALBUM)
{
retVal = ProcessDependentStringOption(clpp, option,
metaProcessorVars, MetaInfo::StringMetaItem_Album);
}
else if(strOption == OPTION_STRING_GENRE)
{
retVal = ProcessDependentStringOption(clpp, option,