Expand Audacity

Thank you so much Edgar!! :smiley:
It really seems to work now as I wanted: C:>“C:UsersmeDesktopaudacity-src - unA2LinuxwinReleaseAudacity.exe” -output “C:UsersmeDesktopoutputedited_1.wav” -input “C:UsersmeDesktopintput with spaces1.wav”

For the sake of completeness the code (based on Edgar’s UnA2Linux-files, my improvements marked with //mytry):

  • My OnInit()-function in AudacityApp.cpp:
bool AudacityApp::OnInit()
{
//efm5 start new
   SetCLIpath(wxGetCwd());
   mbDoUnattended = false;
   mbDoTo4 = false;
   mbSilenceProject = false;
   mbAmplify = false;
   mbDoPrompt = false;
   mbFileNameError = false;
   mbNeedToSave = true;
   mbSaveAsSet = false; //mytry
//efm5 end new
   m_aliasMissingWarningShouldShow = true;
   m_LastMissingBlockFile = NULL;

#if defined(__WXGTK__)
   // Workaround for bug 154 -- initialize to false
   inKbdHandler = false;
#endif

#if defined(__WXMAC__)
   // Disable window animation
   wxSystemOptions::SetOption( wxMAC_WINDOW_PLAIN_TRANSITION, 1 );
#endif

//MERGE:
//Everything now uses Audacity name for preferences.
//(Audacity and CleanSpeech the same program and use
//the same preferences file).
//
// LL: Moved here from InitPreferences() to ensure VST effect
//     discovery writes configuration to the correct directory
//     on OSX with case-sensitive file systems.
#ifdef AUDACITY_NAME
   wxString appName = wxT(AUDACITY_NAME);
   wxString vendorName = wxT(AUDACITY_NAME);
#else
   wxString vendorName = wxT("Audacity");
   wxString appName = wxT("Audacity");
#endif

   wxTheApp->SetVendorName(vendorName);
   wxTheApp->SetAppName(appName);

#ifdef USE_VST // if no VST support, answer is always no
   // Have we been started to check a plugin?
   if (argc == 3 && wxStrcmp(argv[1], VSTCMDKEY) == 0) {
      wxHandleFatalExceptions();

      VSTEffect::Check(argv[2]);
      return false;
   }
#endif

   #ifndef __WXMAC__
      mLogger = new wxLogWindow(NULL, wxT("Audacity Log"), false, false);
      mLogger->SetActiveTarget(mLogger);
      mLogger->EnableLogging(true);
      mLogger->SetLogLevel(wxLOG_Max);
   #endif

   // Unused strings that we want to be translated, even though
   // we're not using them yet...
   wxString future1 = _("Master Gain Control");
   wxString future2 = _("Input Meter");
   wxString future3 = _("Output Meter");

   ::wxInitAllImageHandlers();

   wxFileSystem::AddHandler(new wxZipFSHandler);

   InitPreferences();

   #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__) && !defined(__CYGWIN__)
      this->AssociateFileTypes(); 
   #endif

   // TODO - read the number of files to store in history from preferences
   mRecentFiles = new FileHistory(ID_RECENT_LAST - ID_RECENT_FIRST + 1, ID_RECENT_CLEAR);
   mRecentFiles->Load(*gPrefs, wxT("RecentFiles"));

   //
   // Paths: set search path and temp dir path
   //

   wxString home = wxGetHomeDir();
   mAppHomeDir = home;
   theTheme.EnsureInitialised();

   // AColor depends on theTheme.
   AColor::Init(); 

   /* On Unix systems, the default temp dir is in /tmp. */
   /* Search path (for plug-ins, translations etc) is (in this order):
      * The AUDACITY_PATH environment variable
      * The current directory
      * The user's .audacity-files directory in their home directory
      * The "share" and "share/doc" directories in their install path */
   #ifdef __WXGTK__
   defaultTempDir.Printf(wxT("/tmp/audacity-%s"), wxGetUserId().c_str());
   
   wxString pathVar = wxGetenv(wxT("AUDACITY_PATH"));
   if (pathVar != wxT(""))
      AddMultiPathsToPathList(pathVar, audacityPathList);
   AddUniquePathToPathList(::wxGetCwd(), audacityPathList);
   AddUniquePathToPathList(wxString::Format(wxT("%s/.audacity-files"),
                                            home.c_str()),
                           audacityPathList);
   #ifdef AUDACITY_NAME
      AddUniquePathToPathList(wxString::Format(wxT("%s/share/%s"),
                                               wxT(INSTALL_PREFIX), wxT(AUDACITY_NAME)),
                              audacityPathList);
      AddUniquePathToPathList(wxString::Format(wxT("%s/share/doc/%s"),
                                               wxT(INSTALL_PREFIX), wxT(AUDACITY_NAME)),
                              audacityPathList);
   #else //AUDACITY_NAME
      AddUniquePathToPathList(wxString::Format(wxT("%s/share/audacity"),
                                               wxT(INSTALL_PREFIX)),
                              audacityPathList);
      AddUniquePathToPathList(wxString::Format(wxT("%s/share/doc/audacity"),
                                               wxT(INSTALL_PREFIX)),
                              audacityPathList);
   #endif //AUDACITY_NAME

   AddUniquePathToPathList(wxString::Format(wxT("%s/share/locale"),
                                            wxT(INSTALL_PREFIX)),
                           audacityPathList);

   #endif //__WXGTK__

   wxFileName tmpFile;
   tmpFile.AssignTempFileName(wxT("nn"));
   wxString tmpDirLoc = tmpFile.GetPath(wxPATH_GET_VOLUME);
   ::wxRemoveFile(tmpFile.GetFullPath());

   // On Mac and Windows systems, use the directory which contains Audacity.
   #ifdef __WXMSW__
   // On Windows, the path to the Audacity program is in argv[0]
   wxString progPath = wxPathOnly(argv[0]);
   AddUniquePathToPathList(progPath, audacityPathList);
   AddUniquePathToPathList(progPath+wxT("\Languages"), audacityPathList);
   
   defaultTempDir.Printf(wxT("%s\audacity_temp"), 
                         tmpDirLoc.c_str());
   #endif //__WXWSW__

   #ifdef __WXMAC__
   // On Mac OS X, the path to the Audacity program is in argv[0]
   wxString progPath = wxPathOnly(argv[0]);

   AddUniquePathToPathList(progPath, audacityPathList);
   // If Audacity is a "bundle" package, then the root directory is
   // the great-great-grandparent of the directory containing the executable.
   AddUniquePathToPathList(progPath+wxT("/../../../"), audacityPathList);

   AddUniquePathToPathList(progPath+wxT("/Languages"), audacityPathList);
   AddUniquePathToPathList(progPath+wxT("/../../../Languages"), audacityPathList);
   defaultTempDir.Printf(wxT("%s/audacity-%s"), 
                         tmpDirLoc.c_str(),
                         wxGetUserId().c_str());
   #endif //__WXMAC__

   // BG: Create a temporary window to set as the top window
   wxFrame *temporarywindow = new wxFrame(NULL, -1, wxT("temporarytopwindow"));
   SetTopWindow(temporarywindow);

   // Initialize the ModuleManager
   ModuleManager::Initialize();

   // Initialize the CommandHandler
   InitCommandHandler();

   // load audacity plug-in modules
   LoadModules(*mCmdHandler);

   // Locale
   // wxWidgets 2.3 has a much nicer wxLocale API.  We can make this code much
   // better once we move to wx 2.3/2.4.

   wxString lang = gPrefs->Read(wxT("/Locale/Language"), wxT(""));

   if (lang == wxT(""))
      lang = GetSystemLanguageCode();

#ifdef NOT_RQD
//TIDY-ME: (CleanSpeech) Language prompt??
// The prompt for language only happens ONCE on a system.
// I don't think we should disable it JKC
   wxString lang = gPrefs->Read(wxT("/Locale/Language"), "en");  //lda

// Pop up a dialog the first time the program is run
//lda   if (lang == "")
//lda      lang = ChooseLanguage(NULL);
#endif

   mLocale = NULL;
   InitLang( lang );

   // Init DirManager, which initializes the temp directory
   // If this fails, we must exit the program.

   if (!InitTempDir()) {
      FinishPreferences();
      return false;
   }

   // More initialization
   InitCleanSpeech();

   InitDitherers();
   InitAudioIO();

   LoadEffects();


#ifdef __WXMAC__

   // On the Mac, users don't expect a program to quit when you close the last window.
   // Create a menubar that will show when all project windows are closed.

   wxMenu *fileMenu = new wxMenu();
   wxMenu *recentMenu = new wxMenu();
   fileMenu->Append(wxID_NEW, wxString(_("&New")) + wxT("tCtrl+N"));
   fileMenu->Append(wxID_OPEN, wxString(_("&Open...")) + wxT("tCtrl+O"));
   fileMenu->AppendSubMenu(recentMenu, _("Open &Recent..."));
   fileMenu->Append(wxID_ABOUT, _("&About Audacity..."));
   fileMenu->Append(wxID_PREFERENCES, wxString(_("&Preferences...")) + wxT("tCtrl+,"));

   wxMenuBar *menuBar = new wxMenuBar();
   menuBar->Append(fileMenu, wxT("&File"));

   wxMenuBar::MacSetCommonMenuBar(menuBar);

   mRecentFiles->UseMenu(recentMenu);
   mRecentFiles->AddFilesToMenu(recentMenu);

   // This invisibale frame will be the "root" of all other frames and will
   // become the active frame when no projects are open.
   gParentFrame = new wxFrame(NULL, -1, wxEmptyString, wxPoint(0, 0), wxSize(0, 0), 0);

#endif //__WXMAC__

   SetExitOnFrameDelete(true);
   //efm5 start
#if !defined(__CYGWIN__)//might work on Cygwin
   if (argc > 1) {
      if (!wxString(wxT("-doTo4")).CmpNoCase(argv[1])) {
         mbDoUnattended = true;
         mbDoTo4 = true;
      }
      if (!wxString(wxT("-doTo3")).CmpNoCase(argv[1])) {
         mbDoUnattended = true;
         mbDoTo3 = true;
      }
      else if (!wxString(wxT("-doSilenceProject")).CmpNoCase(argv[1])) {
         mbDoUnattended = true;
         mbSilenceProject = true;
      }
      else if (!wxString(wxT("-doAmplify")).CmpNoCase(argv[1])) {
         mbDoUnattended = true;
         mbAmplify = true;
      }
   }
#endif
   //efm5 end

   AudacityProject *project = CreateNewAudacityProject();
   mCmdHandler->SetProject(project);

   wxWindow * pWnd = MakeHijackPanel() ;
   if( pWnd )
   {
      project->Show( false );
      SetTopWindow(pWnd);
      pWnd->Show( true );
   }

   delete temporarywindow;
   
   if( project->mShowSplashScreen )
      project->OnHelpWelcome();

   // JKC 10-Sep-2007: Enable monitoring from the start.
   // (recommended by lprod.org).
   // Monitoring stops again after any 
   // PLAY or RECORD completes.  
   // So we also call StartMonitoring when STOP is called.
   project->MayStartMonitoring();

   #ifdef __WXMAC__
      mLogger = new wxLogWindow(NULL, wxT("Audacity Log"), false, false);
      mLogger->SetActiveTarget(mLogger);
      mLogger->EnableLogging(true);
      mLogger->SetLogLevel(wxLOG_Max);
   #endif

   #ifdef USE_FFMPEG
   FFmpegStartup();
   #endif

   #ifdef USE_GSTREAMER
   GStreamerStartup();
   #endif

   mImporter = new Importer;

   //
   // Auto-recovery
   //
   bool didRecoverAnything = false;
   if (!ShowAutoRecoveryDialogIfNeeded(&project, &didRecoverAnything))
   {
      // Important: Prevent deleting any temporary files!
      DirManager::SetDontDeleteTempFiles();
      QuitAudacity(true);
   }

   //
   // Command-line parsing, but only if we didn't recover
   //

#if !defined(__CYGWIN__)

   // Parse command-line arguments
   if (argc > 1 && !didRecoverAnything) {
      for (int option = 1; option < argc; option++) {
         if (!argv[option])
            continue;
         bool handled = false;

         if (!wxString(wxT("-help")).CmpNoCase(argv[option])) {
            PrintCommandLineHelp(); // print the help message out
            exit(0);
         }

         if (option < argc - 1 &&
             argv[option + 1] &&
             !wxString(wxT("-blocksize")).CmpNoCase(argv[option])) {
            long theBlockSize;
            if (wxString(argv[option + 1]).ToLong(&theBlockSize)) {
               if (theBlockSize >= 256 && theBlockSize < 100000000) {
                  wxFprintf(stderr, _("Using block size of %ldn"),
                          theBlockSize);
                  Sequence::SetMaxDiskBlockSize(theBlockSize);
               }
            }
            option++;
            handled = true;
         }

         if (!handled && !wxString(wxT("-test")).CmpNoCase(argv[option])) {
            RunBenchmark(NULL);
            exit(0);
         }

         if (!handled && !wxString(wxT("-version")).CmpNoCase(argv[option])) {
            wxPrintf(wxT("Audacity v%s (%s)n"),
                     AUDACITY_VERSION_STRING,
                     (wxUSE_UNICODE ? wxT("Unicode") : wxT("ANSI")));
            exit(0);
         }

        //efm5 start
         if (!handled && !wxString(wxT("-doTo3")).CmpNoCase(argv[option])) {
            if (!project)
               project = CreateNewAudacityProject();
            handled = true;
         }
         if (!handled && !wxString(wxT("-doTo4")).CmpNoCase(argv[option])) {
            if (!project)
               project = CreateNewAudacityProject();
            handled = true;
         }
         if (!handled && !wxString(wxT("-doSilenceProject")).CmpNoCase(argv[option])) {
            if (!project)
               project = CreateNewAudacityProject();
            wxString tempFilename(GetCLIpath());
            tempFilename.Append(wxT("\"));//must escape NEWLINE to compile
            tempFilename.Append(argv[option+1]);
            mUnattendedProjectName = tempFilename;
            handled = true;
         }
         if (!handled && !wxString(wxT("-doAmplify")).CmpNoCase(argv[option])) {
            if (!project)
               project = CreateNewAudacityProject();
            wxString tempFilename(GetCLIpath());
            tempFilename.Append(wxT("\"));//must escape NEWLINE to compile
            tempFilename.Append(argv[option+1]);
            mUnattendedProjectName = tempFilename;
            handled = true;
         }
         //efm5 end
	 //mytry start
         if (!handled && !wxString(wxT("-output")).CmpNoCase(argv[option])) {
            mSaveAsFileName = argv[option+1];
            mbSaveAsSet = true;
            handled = true;
         }
         if (!handled && !wxString(wxT("-input")).CmpNoCase(argv[option])) {
            if (!project)
               project = CreateNewAudacityProject();
            wxFileName fn(argv[option+1]);
            project->OpenFile(fn.GetFullPath());
            handled = true;
         }
		 //mytry end

         if (argv[option][0] == wxT('-') && !handled) {
            wxPrintf(_("Unknown command line option: %sn"), argv[option]);
            exit(0);
         }

		 /*//mytry start
         if (!handled)
         {
            if (!project)
            {
               // Create new window for project
               project = CreateNewAudacityProject();
            }
            //efm5 start
			wxString tempFN(GetCLIpath());
            tempFN.Append(wxT("\"));//must escape NEWLINE to compile
            tempFN.Append(argv[option]);
            project->OpenFile(tempFN);
            if (mbDoUnattended) {
               wxSetWorkingDirectory(GetCLIpath());
               project->UnattendedCLIAction();
            }

            // Always open files with an absolute path
            //wxFileName fn(argv[option]);
            //fn.MakeAbsolute();
            //project->OpenFile(fn.GetFullPath());
            //efm5 end
            project = NULL; // don't reuse this project for other file
         }
		 *///mytry end
      }                         // for option...
   }                            // if (argc>1)

#else //__CYGWIN__
   
   // Cygwin command line parser (by Dave Fancella)
   if (argc > 1 && !didRecoverAnything) {
      int optionstart = 1;
      bool startAtOffset = false;
      
      // Scan command line arguments looking for trouble
      for (int option = 1; option < argc; option++) {
         if (!argv[option])
            continue;
         // Check to see if argv[0] is copied across other arguments.
         // This is the reason Cygwin gets its own command line parser.
         if (wxString(argv[option]).Lower().Contains(wxString(wxT("audacity.exe")))) {
            startAtOffset = true;
            optionstart = option + 1;
         }
      }
      
      for (int option = optionstart; option < argc; option++) {
         if (!argv[option])
            continue;
         bool handled = false;
         bool openThisFile = false;
         wxString fileToOpen;
         
         if (!wxString(wxT("-help")).CmpNoCase(argv[option])) {
            PrintCommandLineHelp(); // print the help message out
            exit(0);
         }

         if (option < argc - 1 &&
             argv[option + 1] &&
             !wxString(wxT("-blocksize")).CmpNoCase(argv[option])) {
            long theBlockSize;
            if (wxString(argv[option + 1]).ToLong(&theBlockSize)) {
               if (theBlockSize >= 256 && theBlockSize < 100000000) {
                  wxFprintf(stderr, _("Using block size of %ldn"),
                          theBlockSize);
                  Sequence::SetMaxDiskBlockSize(theBlockSize);
               }
            }
            option++;
            handled = true;
         }

         if (!handled && !wxString(wxT("-test")).CmpNoCase(argv[option])) {
            RunBenchmark(NULL);
            exit(0);
         }

         if (argv[option][0] == wxT('-') && !handled) {
            wxPrintf(_("Unknown command line option: %sn"), argv[option]);
            exit(0);
         }
         
         if(handled)
            fileToOpen.Clear();
         
         if (!handled)
            fileToOpen = fileToOpen + wxT(" ") + argv[option];
         if(wxString(argv[option]).Lower().Contains(wxT(".aup")))
            openThisFile = true;
         if(openThisFile) {
            openThisFile = false;
            if (!project)
            {
               // Create new window for project
               project = CreateNewAudacityProject();
            }
            project->OpenFile(fileToOpen);
            project = NULL; // don't reuse this project for other file
         }

      }                         // for option...
   }                            // if (argc>1)

#endif // __CYGWIN__ (Cygwin command-line parser)

   gInited = true;
   
   ModuleManager::Dispatch(AppInitialized);

   mWindowRectAlreadySaved = FALSE;

   wxLog::FlushActive(); // Make sure all log messages are written.

   mTimer = new wxTimer(this, kAudacityAppTimerID);
   mTimer->Start(200);
   return TRUE;
}
  • My OnCloseWindow file-saving (after Edgar’s efm paragraph):
   //efm5 start
   //if (event.CanVeto() && (mEmptyCanBeDirty || bHasTracks)) {
   //   if (mUndoManager.UnsavedChanges()) {
   //      wxString Message = _("Save changes before closing?");
   //      if( !bHasTracks )
   //      { 
   //       Message += _("nIf saved, the project will have no tracks.nnTo save any previously open tracks:nCancel, Edit > Undo until all tracksnare open, then File > Save Project.");
   //      }
   //      int result = wxMessageBox( Message,
   //                                _("Save changes?"),
   //                                wxYES_NO | wxCANCEL | wxICON_QUESTION,
   //                                this);

   //      if (result == wxCANCEL || (result == wxYES && !Save())) {
   //         event.Veto();
   //         return;
   //      }
   //   }
   //}
   //efm5 end
   //mytry start
   bool bSaveFile = wxGetApp().GetSaveAsSet();
   if (bSaveFile && (!mEmptyCanBeDirty || bHasTracks))
   {
	   wxFileName tempFileName(wxGetApp().GetSaveAsFileName());
	   wxString tempName(tempFileName.GetFullPath());
	   OnExport(wxT("WAV"), tempName);
   }
   //mytry end
  • And of course the declarations in AudacityApp.h:
//efm5 start new
// store the current working directory as it exists when Audacity is launched
//(it gets hijacked somewhere -- see Project.cpp line #758
private:
   wxString mCLIpath;
   wxFileName mUnattendedProjectName;
   wxFileName mSaveAsFileName; //mytry
   void SetCLIpath(const wxString & CLIpath) {mCLIpath = CLIpath;};
   bool mbNeedToSave;
   bool mbDoUnattended;
   bool mbDoTo4;
   bool mbDoTo3;
   bool mbSilenceProject;
   bool mbAmplify;
   bool mbDoPrompt;
   bool mbFileNameError;
   bool mbSaveAsSet; //mytry
public:
   const wxString & GetCLIpath() const {return mCLIpath;};
   const wxFileName & GetUnattendedProjectName() const {return mUnattendedProjectName;};
   const wxFileName & GetSaveAsFileName() const {return mSaveAsFileName;}; //mytry
   bool GetDoUnattended() const {return mbDoUnattended;};
   bool GetDoTo4() const {return mbDoTo4;};
   bool GetDoTo3() const {return mbDoTo3;};
   bool GetDoSilenceProject() const {return mbSilenceProject;};
   bool GetDoAmplifyProject() const {return mbAmplify;};
   bool GetDoPrompt() const {return mbDoPrompt;};
   bool GetFileNameError() const {return mbFileNameError;};
   void SetFileNameError(bool pError) {mbFileNameError = pError;};
   void SetNeedToSave(bool pNeedToSave) {mbNeedToSave = pNeedToSave;};
   bool GetNeedToSave() const {return mbNeedToSave;};
   bool GetSaveAsSet() const {return mbSaveAsSet;}; //mytry
//efm5 end new
};

Another little adaption which I made was:

  • I’d like to save wav-files only as mono, so I changed line 3116 in Menus.cpp:
//efm5 start
void AudacityProject::OnExport(const wxString & FormatType, const wxString & FileName)
{
   Exporter e;
   //this version of Exporter::Process bypasses the Save dialog
   e.Process(this, 1, FormatType, FileName, false, 0.0, mTracks->GetEndTime()); //mytry: changed 2nd argument (number of channels) from 2 to 1
}
//efm5 end

EDIT:
One more thing came to my mind: maybe it would be a good idea to parse the CLI-input (argv[option+1]) through the wxT-function in case somebody wants a unicode compatible solution.

mSaveAsFileName = wxT(argv[option+1]);

and

wxFileName fn(wxT(argv[option+1]));