2015-09-06 20:20:00 +02:00
# include "../cli/mainfeatures.h"
2015-04-22 19:33:53 +02:00
# if defined(GUI_QTWIDGETS)
2015-09-06 20:20:00 +02:00
# include ".. / gui / initiate.h"
2016-07-27 18:31:42 +02:00
# include ". / knownfieldmodel.h"
2015-04-22 19:33:53 +02:00
# elif defined(GUI_QTQUICK)
# endif
2015-12-08 08:40:03 +01:00
# include "resources/config.h"
2015-12-05 22:55:05 +01:00
2015-04-22 19:33:53 +02:00
# if defined(GUI_QTWIDGETS) || defined(GUI_QTQUICK)
# include <qtutilities / resources / qtconfigarguments.h>
# else
# include <c++utilities / application / fakeqtconfigarguments.h>
# endif
2015-09-01 20:20:15 +02:00
# include <c++utilities/application/commandlineutils.h>
2015-04-22 19:33:53 +02:00
# include <c++utilities/application/failure.h>
# include <iostream>
# include <memory>
# include <functional>
using namespace std ;
using namespace std : : placeholders ;
using namespace ApplicationUtilities ;
2015-11-28 00:20:49 +01:00
namespace Cli {
SetTagInfoArgs : : SetTagInfoArgs ( Argument & filesArg , Argument & verboseArg ) :
filesArg ( filesArg ) ,
verboseArg ( verboseArg ) ,
2016-06-14 00:52:33 +02:00
docTitleArg ( " doc-title " , ' d ' , " specifies the document title (has no affect if not supported by the container) " ) ,
2016-07-31 23:22:22 +02:00
removeOtherFieldsArg ( " remove-other-fields " , ' \0 ' , " removes ALL fields where no value has been provided for (to remove a specific field use eg. \" album= \" ) " ) ,
2016-06-14 00:52:33 +02:00
treatUnknownFilesAsMp3FilesArg ( " treat-unknown-as-mp3 " , ' \0 ' , " if present unknown files will be treatet as MP3 files " ) ,
id3v1UsageArg ( " id3v1-usage " , ' \0 ' , " specifies the ID3v1 usage (only used when already present by default); only relevant when dealing with MP3 files (or files treated as such) " ) ,
id3v2UsageArg ( " id3v2-usage " , ' \0 ' , " specifies the ID3v2 usage (always used by default); only relevant when dealing with MP3 files (or files treated as such) " ) ,
mergeMultipleSuccessiveTagsArg ( " merge-successive-tags " , ' \0 ' , " if present multiple successive ID3v2 tags will be merged " ) ,
id3v2VersionArg ( " id3v2-version " , ' \0 ' , " forces a specific ID3v2 version to be used; only relevant when ID3v2 is used " ) ,
encodingArg ( " encoding " , ' \0 ' , " specifies the preferred encoding " ) ,
2016-07-31 23:22:22 +02:00
removeTargetArg ( " remove-target " , ' \0 ' , " removes all tags with the specified target " ) ,
addAttachmentArg ( " add-attachment " , ' \0 ' , " adds a new attachment " ) ,
updateAttachmentArg ( " update-attachment " , ' \0 ' , " updates an existing attachment " ) ,
removeAttachmentArg ( " remove-attachment " , ' \0 ' , " removes an existing attachment " ) ,
removeExistingAttachmentsArg ( " remove-existing-attachments " , ' r ' , " removes ALL existing attachments (to remove a specific attachment use --remove-attachment) " ) ,
2016-06-14 00:52:33 +02:00
minPaddingArg ( " min-padding " , ' \0 ' , " specifies the minimum padding before the media data " ) ,
maxPaddingArg ( " max-padding " , ' \0 ' , " specifies the maximum padding before the media data " ) ,
prefPaddingArg ( " preferred-padding " , ' \0 ' , " specifies the preferred padding before the media data " ) ,
tagPosValueArg ( " value " , ' v ' , " specifies the position, either front, back or current " ) ,
forceTagPosArg ( " force " , ' f ' , " forces the specified position even if the file to be rewritten " ) ,
tagPosArg ( " tag-pos " , ' \0 ' , " specifies the preferred tag position " ) ,
indexPosValueArg ( " value " , ' v ' , " specifies the position, either front, back or current " ) ,
forceIndexPosArg ( " force " , ' f ' , " forces the specified position even if the file to be rewritten " ) ,
indexPosArg ( " index-pos " , ' \0 ' , " specifies the preferred index position " ) ,
forceRewriteArg ( " force-rewrite " , ' \0 ' , " forces the file to rewritten from the scratch " ) ,
2016-07-04 23:28:11 +02:00
valuesArg ( " values " , ' n ' , " specifies the values to be set " ) ,
2016-07-31 23:22:22 +02:00
setTagInfoArg ( " set " , ' s ' , " sets the specified tag information and attachments " )
2015-11-28 00:20:49 +01:00
{
docTitleArg . setCombinable ( true ) ;
docTitleArg . setRequiredValueCount ( - 1 ) ;
docTitleArg . setValueNames ( { " title of first segment " , " title of second segment " } ) ;
removeOtherFieldsArg . setCombinable ( true ) ;
treatUnknownFilesAsMp3FilesArg . setCombinable ( true ) ;
id3v1UsageArg . setRequiredValueCount ( 1 ) ;
id3v1UsageArg . setValueNames ( { " always/keepexisting/never " } ) ;
2016-07-04 23:28:11 +02:00
id3v1UsageArg . setPreDefinedCompletionValues ( " always keepexisting never " ) ;
2015-11-28 00:20:49 +01:00
id3v1UsageArg . setCombinable ( true ) ;
id3v2UsageArg . setRequiredValueCount ( 1 ) ;
id3v2UsageArg . setValueNames ( { " always/keepexisting/never " } ) ;
2016-07-04 23:28:11 +02:00
id3v2UsageArg . setPreDefinedCompletionValues ( " always keepexisting never " ) ;
2015-11-28 00:20:49 +01:00
id3v2UsageArg . setCombinable ( true ) ;
mergeMultipleSuccessiveTagsArg . setCombinable ( true ) ;
id3v2VersionArg . setRequiredValueCount ( 1 ) ;
id3v2VersionArg . setValueNames ( { " ID3v2 version " } ) ;
id3v2VersionArg . setCombinable ( true ) ;
encodingArg . setRequiredValueCount ( 1 ) ;
encodingArg . setValueNames ( { " latin1/utf8/utf16le/utf16be " } ) ;
2016-07-04 23:28:11 +02:00
encodingArg . setPreDefinedCompletionValues ( " latin1 utf8 utf16le utf16be " ) ;
2015-11-28 00:20:49 +01:00
encodingArg . setCombinable ( true ) ;
2016-07-31 23:22:22 +02:00
removeTargetArg . setRequiredValueCount ( - 1 ) ;
removeTargetArg . setValueNames ( { } ) ;
removeTargetArg . setCombinable ( true ) ;
removeTargetArg . setConstraints ( 0 , - 1 ) ;
addAttachmentArg . setRequiredValueCount ( - 1 ) ;
addAttachmentArg . setValueNames ( { " path=some/file " , " name=Some name " , " desc=Some desc " , " mime=mime/type " } ) ;
addAttachmentArg . setCombinable ( true ) ;
addAttachmentArg . setConstraints ( 0 , - 1 ) ;
addAttachmentArg . setValueCompletionBehavior ( ValueCompletionBehavior : : PreDefinedValues | ValueCompletionBehavior : : AppendEquationSign ) ;
addAttachmentArg . setPreDefinedCompletionValues ( " name id path desc mime " ) ;
updateAttachmentArg . setRequiredValueCount ( - 1 ) ;
updateAttachmentArg . setValueNames ( { " path=some/file " , " name=Some name " , " desc=Some desc " , " mime=mime/type " } ) ;
updateAttachmentArg . setCombinable ( true ) ;
updateAttachmentArg . setConstraints ( 0 , - 1 ) ;
updateAttachmentArg . setValueCompletionBehavior ( ValueCompletionBehavior : : PreDefinedValues | ValueCompletionBehavior : : AppendEquationSign ) ;
updateAttachmentArg . setPreDefinedCompletionValues ( " name id path desc mime " ) ;
removeAttachmentArg . setRequiredValueCount ( 1 ) ;
removeAttachmentArg . setValueNames ( { " name=to_remove " } ) ;
removeAttachmentArg . setCombinable ( true ) ;
removeAttachmentArg . setConstraints ( 0 , - 1 ) ;
removeAttachmentArg . setPreDefinedCompletionValues ( " name id " ) ;
removeAttachmentArg . setValueCompletionBehavior ( ValueCompletionBehavior : : PreDefinedValues | ValueCompletionBehavior : : AppendEquationSign ) ;
2015-11-28 00:20:49 +01:00
removeExistingAttachmentsArg . setCombinable ( true ) ;
minPaddingArg . setRequiredValueCount ( 1 ) ;
minPaddingArg . setValueNames ( { " min padding in byte " } ) ;
minPaddingArg . setCombinable ( true ) ;
maxPaddingArg . setRequiredValueCount ( 1 ) ;
maxPaddingArg . setValueNames ( { " min padding in byte " } ) ;
maxPaddingArg . setCombinable ( true ) ;
prefPaddingArg . setRequiredValueCount ( 1 ) ;
prefPaddingArg . setValueNames ( { " preferred padding in byte " } ) ;
prefPaddingArg . setCombinable ( true ) ;
2016-06-14 00:52:33 +02:00
tagPosValueArg . setRequiredValueCount ( 1 ) ;
2016-07-04 23:28:11 +02:00
tagPosValueArg . setValueNames ( { " front/back/current " } ) ;
tagPosValueArg . setPreDefinedCompletionValues ( " front back current " ) ;
tagPosValueArg . setImplicit ( true ) ;
forceTagPosArg . setCombinable ( true ) ;
2015-11-28 00:20:49 +01:00
tagPosArg . setCombinable ( true ) ;
2016-06-14 00:52:33 +02:00
tagPosArg . setSubArguments ( { & tagPosValueArg , & forceTagPosArg } ) ;
forceIndexPosArg . setCombinable ( true ) ;
2016-07-04 23:28:11 +02:00
indexPosValueArg . setRequiredValueCount ( 1 ) ;
indexPosValueArg . setValueNames ( { " front/back/current " } ) ;
indexPosValueArg . setPreDefinedCompletionValues ( " front back current " ) ;
indexPosValueArg . setImplicit ( true ) ;
2015-11-28 00:20:49 +01:00
indexPosArg . setCombinable ( true ) ;
2016-06-14 00:52:33 +02:00
indexPosArg . setSubArguments ( { & indexPosValueArg , & forceIndexPosArg } ) ;
2015-11-28 00:20:49 +01:00
forceRewriteArg . setCombinable ( true ) ;
2016-06-14 00:52:33 +02:00
valuesArg . setValueNames ( { " title=foo " , " album=bar " , " cover=/path/to/file " } ) ;
valuesArg . setRequiredValueCount ( - 1 ) ;
valuesArg . setImplicit ( true ) ;
2016-07-31 23:22:22 +02:00
valuesArg . setPreDefinedCompletionValues ( Cli : : fieldNamesForSet ) ;
2016-07-04 23:28:11 +02:00
valuesArg . setValueCompletionBehavior ( ValueCompletionBehavior : : PreDefinedValues | ValueCompletionBehavior : : AppendEquationSign ) ;
2015-11-28 00:20:49 +01:00
setTagInfoArg . setDenotesOperation ( true ) ;
2016-06-25 23:11:16 +02:00
setTagInfoArg . setCallback ( std : : bind ( Cli : : setTagInfo , std : : cref ( * this ) ) ) ;
2016-06-14 00:52:33 +02:00
setTagInfoArg . setSubArguments ( { & valuesArg , & filesArg , & docTitleArg , & removeOtherFieldsArg , & treatUnknownFilesAsMp3FilesArg , & id3v1UsageArg , & id3v2UsageArg ,
2016-07-31 23:22:22 +02:00
& mergeMultipleSuccessiveTagsArg , & id3v2VersionArg , & encodingArg , & removeTargetArg , & addAttachmentArg , & updateAttachmentArg , & removeAttachmentArg ,
2015-11-28 00:20:49 +01:00
& removeExistingAttachmentsArg , & minPaddingArg , & maxPaddingArg , & prefPaddingArg , & tagPosArg ,
& indexPosArg , & forceRewriteArg , & verboseArg } ) ;
}
}
2015-04-22 19:33:53 +02:00
int main ( int argc , char * argv [ ] )
{
// setup argument parser
ArgumentParser parser ;
2015-08-25 19:09:26 +02:00
SET_APPLICATION_INFO ;
2015-04-22 19:33:53 +02:00
QT_CONFIG_ARGUMENTS qtConfigArgs ;
HelpArgument helpArg ( parser ) ;
2015-09-23 00:02:06 +02:00
// verbose option
2016-06-14 00:52:33 +02:00
Argument verboseArg ( " verbose " , ' v ' , " be verbose " ) ;
2015-09-23 00:02:06 +02:00
verboseArg . setCombinable ( true ) ;
2015-04-22 19:33:53 +02:00
// recursive option
2016-06-14 00:52:33 +02:00
Argument recursiveArg ( " recursive " , ' r ' , " includes subdirectories " ) ;
2015-04-22 19:33:53 +02:00
// input/output file/files
2016-06-14 00:52:33 +02:00
Argument fileArg ( " file " , ' f ' , " specifies the path of the file to be opened " ) ;
2015-04-22 19:33:53 +02:00
fileArg . setValueNames ( { " path " } ) ;
fileArg . setRequiredValueCount ( 1 ) ;
2016-06-14 00:52:33 +02:00
fileArg . setCombinable ( true ) ;
Argument defaultFileArg ( fileArg ) ;
defaultFileArg . setImplicit ( true ) ;
Argument filesArg ( " files " , ' f ' , " specifies the path of the file(s) to be opened " ) ;
filesArg . setValueNames ( { " path 1 " , " path 2 " } ) ;
filesArg . setRequiredValueCount ( - 1 ) ;
filesArg . setCombinable ( true ) ;
Argument outputFileArg ( " output-file " , ' o ' , " specifies the path of the output file " ) ;
2015-04-22 19:33:53 +02:00
outputFileArg . setValueNames ( { " path " } ) ;
outputFileArg . setRequiredValueCount ( 1 ) ;
outputFileArg . setCombinable ( true ) ;
// print field names
2016-06-14 00:52:33 +02:00
Argument printFieldNamesArg ( " print-field-names " , ' \0 ' , " prints available field names " ) ;
2015-04-22 19:33:53 +02:00
printFieldNamesArg . setCallback ( Cli : : printFieldNames ) ;
2015-08-09 23:53:45 +02:00
// display general file info
2016-07-31 23:22:22 +02:00
Argument displayFileInfoArg ( " info " , ' i ' , " displays general file information " ) ;
2015-08-09 23:53:45 +02:00
displayFileInfoArg . setDenotesOperation ( true ) ;
2015-09-23 00:02:06 +02:00
displayFileInfoArg . setCallback ( std : : bind ( Cli : : displayFileInfo , _1 , std : : cref ( filesArg ) , std : : cref ( verboseArg ) ) ) ;
2016-06-14 00:52:33 +02:00
displayFileInfoArg . setSubArguments ( { & filesArg , & verboseArg } ) ;
2015-04-22 19:33:53 +02:00
// display tag info
2016-06-14 00:52:33 +02:00
Argument fieldsArg ( " fields " , ' n ' , " specifies the field names to be displayed " ) ;
fieldsArg . setValueNames ( { " title " , " album " , " artist " , " trackpos " } ) ;
fieldsArg . setRequiredValueCount ( - 1 ) ;
2016-07-04 23:28:11 +02:00
fieldsArg . setPreDefinedCompletionValues ( Cli : : fieldNames ) ;
2016-06-14 00:52:33 +02:00
fieldsArg . setImplicit ( true ) ;
Argument displayTagInfoArg ( " get " , ' g ' , " displays the values of all specified tag fields (displays all fields if none specified) " ) ;
2015-07-27 23:29:30 +02:00
displayTagInfoArg . setDenotesOperation ( true ) ;
2016-06-25 23:11:16 +02:00
displayTagInfoArg . setCallback ( std : : bind ( Cli : : displayTagInfo , std : : cref ( fieldsArg ) , std : : cref ( filesArg ) , std : : cref ( verboseArg ) ) ) ;
2016-06-14 00:52:33 +02:00
displayTagInfoArg . setSubArguments ( { & fieldsArg , & filesArg , & verboseArg } ) ;
2015-04-22 19:33:53 +02:00
// set tag info
2015-11-28 00:20:49 +01:00
Cli : : SetTagInfoArgs setTagInfoArgs ( filesArg , verboseArg ) ;
2015-04-22 19:33:53 +02:00
// extract cover
2016-06-14 00:52:33 +02:00
Argument fieldArg ( " fields " , ' n ' , " specifies the field to be extracted " ) ;
fieldArg . setValueNames ( { " field name " } ) ;
fieldArg . setRequiredValueCount ( 1 ) ;
fieldArg . setImplicit ( true ) ;
2016-07-31 23:22:22 +02:00
Argument extractFieldArg ( " extract " , ' e ' , " saves the value of the specified field (eg. cover or other binary field) to the specified file or writes it to stdout if no output file has been specified " ) ;
2016-06-14 00:52:33 +02:00
extractFieldArg . setSubArguments ( { & fieldArg , & fileArg , & outputFileArg , & verboseArg } ) ;
2015-07-27 23:29:30 +02:00
extractFieldArg . setDenotesOperation ( true ) ;
2016-06-25 23:11:16 +02:00
extractFieldArg . setCallback ( std : : bind ( Cli : : extractField , std : : cref ( fieldsArg ) , std : : cref ( fileArg ) , std : : cref ( outputFileArg ) , std : : cref ( verboseArg ) ) ) ;
2015-04-22 19:33:53 +02:00
// file info
2016-06-14 00:52:33 +02:00
Argument validateArg ( " validate " , ' c ' , " validates the file integrity as accurately as possible; the structure of the file will be parsed completely " ) ;
2015-04-22 19:33:53 +02:00
validateArg . setCombinable ( true ) ;
2016-06-14 00:52:33 +02:00
Argument genInfoArg ( " html-info " , ' \0 ' , " generates technical information about the specified file as HTML document " ) ;
2015-07-27 23:29:30 +02:00
genInfoArg . setDenotesOperation ( true ) ;
2016-06-14 00:52:33 +02:00
genInfoArg . setSubArguments ( { & fileArg , & validateArg , & outputFileArg } ) ;
2015-04-22 19:33:53 +02:00
genInfoArg . setCallback ( std : : bind ( Cli : : generateFileInfo , _1 , std : : cref ( fileArg ) , std : : cref ( outputFileArg ) , std : : cref ( validateArg ) ) ) ;
2016-01-14 23:53:28 +01:00
// renaming utility
2016-06-14 00:52:33 +02:00
Argument renamingUtilityArg ( " renaming-utility " , ' \0 ' , " launches the renaming utility instead of the main GUI " ) ;
2016-01-14 23:53:28 +01:00
renamingUtilityArg . setCombinable ( true ) ;
// set arguments to parser
2016-06-14 00:52:33 +02:00
qtConfigArgs . qtWidgetsGuiArg ( ) . setAbbreviation ( ' \0 ' ) ;
qtConfigArgs . qtWidgetsGuiArg ( ) . addSubArgument ( & defaultFileArg ) ;
qtConfigArgs . qtWidgetsGuiArg ( ) . addSubArgument ( & renamingUtilityArg ) ;
2016-07-11 21:15:58 +02:00
parser . setMainArguments ( { & qtConfigArgs . qtWidgetsGuiArg ( ) , & printFieldNamesArg , & displayFileInfoArg , & displayTagInfoArg , & setTagInfoArgs . setTagInfoArg , & extractFieldArg , & genInfoArg , & helpArg } ) ;
2015-04-22 19:33:53 +02:00
// parse given arguments
try {
parser . parseArgs ( argc , argv ) ;
if ( qtConfigArgs . areQtGuiArgsPresent ( ) ) {
# ifdef GUI_QTWIDGETS
2016-06-14 00:52:33 +02:00
return QtGui : : runWidgetsGui ( argc , argv , qtConfigArgs , defaultFileArg . isPresent ( ) & & ! defaultFileArg . values ( ) . empty ( ) ? QString : : fromLocal8Bit ( defaultFileArg . values ( ) . front ( ) ) : QString ( ) , renamingUtilityArg . isPresent ( ) ) ;
2015-04-22 19:33:53 +02:00
# else
2015-09-01 20:20:15 +02:00
CMD_UTILS_START_CONSOLE ;
2016-06-14 00:52:33 +02:00
cerr < < " Application has not been build with Qt widgets GUI support. " < < endl ;
2015-04-22 19:33:53 +02:00
# endif
}
2016-03-28 20:28:59 +02:00
} catch ( const Failure & ex ) {
2015-09-01 20:20:15 +02:00
CMD_UTILS_START_CONSOLE ;
2016-06-14 00:52:33 +02:00
cerr < < " Unable to parse arguments. " < < ex . what ( ) < < " \n See --help for available commands. " < < endl ;
2015-04-22 19:33:53 +02:00
}
return 0 ;
}
2015-11-28 00:20:49 +01:00