Audacity  2.2.2
BatchCommands.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 
3  Audacity: A Digital Audio Editor
4 
5  BatchCommands.cpp
6 
7  Dominic Mazzoni
8  James Crook
9 
10 ********************************************************************//*******************************************************************/
17 
18 
19 #include "Audacity.h"
20 #include "BatchCommands.h"
21 
22 #include <wx/defs.h>
23 #include <wx/dir.h>
24 #include <wx/filedlg.h>
25 #include <wx/textfile.h>
26 
27 #include "AudacityApp.h"
28 #include "Project.h"
30 #include "effects/EffectManager.h"
31 #include "FileNames.h"
32 #include "Internat.h"
33 #include "PluginManager.h"
34 #include "Prefs.h"
35 #include "Shuttle.h"
36 #include "export/ExportFLAC.h"
37 #include "export/ExportMP3.h"
38 #include "export/ExportOGG.h"
39 #include "export/ExportPCM.h"
40 
41 #include "Theme.h"
42 #include "AllThemeResources.h"
43 
44 #include "Track.h"
45 #include "widgets/ErrorDialog.h"
46 
47 // KLUDGE: All commands should be on the same footing
48 // however, for historical reasons we distinguish between
49 // - Effects (which are looked up in effects lists)
50 // - Menu commands (which are held in command manager)
51 // - Specials (which we deal with specially here)
53 
54 // TIDY-ME: Not currently translated,
55 // but there are issues to address if we do.
56 // CLEANSPEECH remnant
57 static const std::pair<const wxChar*, const wxChar*> SpecialCommands[] = {
58  // Use translations of the first members, some other day.
59  // For 2.2.2 we'll get them into the catalog at least.
60 
61  { XO("No Action"), wxT("NoAction") },
62 
63  // { wxT("Import"), wxT("Import") }, // non-functioning
64  /* i18n-hint: before is adverb; MP3 names an audio file format */
65  { XO("Export as MP3 56k before"), wxT("ExportMP3_56k_before") },
66 
67  /* i18n-hint: after is adverb; MP3 names an audio file format */
68  { XO("Export as MP3 56k after"), wxT("ExportMP3_56k_after") },
69 
70  /* i18n-hint: FLAC names an audio file format */
71  { XO("Export as FLAC"), wxT("ExportFLAC") },
72 
73  /* i18n-hint: MP3 names an audio file format */
74  { XO("Export as MP3"), wxT("ExportMP3") },
75 
76  /* i18n-hint: Ogg names an audio file format */
77  { XO("Export as Ogg"), wxT("ExportOgg") },
78 
79  /* i18n-hint: WAV names an audio file format */
80  { XO("Export as WAV"), wxT("ExportWAV") },
81 };
82 // end CLEANSPEECH remnant
83 
84 static const wxString MP3Conversion = wxT("MP3 Conversion");
85 
87 {
88  mMessage = "";
89  ResetChain();
90 
91  wxArrayString names = GetNames();
92 
93  if (names.Index(MP3Conversion) == wxNOT_FOUND) {
97  }
98 }
99 
100 wxString BatchCommands::GetCommand(int index)
101 {
102  if (index < 0 || index >= (int)mCommandChain.GetCount()) {
103  return wxT("");
104  }
105 
106  return mCommandChain[index];
107 }
108 
109 wxString BatchCommands::GetParams(int index)
110 {
111  if (index < 0 || index >= (int)mParamsChain.GetCount()) {
112  return wxT("");
113  }
114 
115  return mParamsChain[index];
116 }
117 
119 {
120  return (int)mCommandChain.GetCount();
121 }
122 
123 bool BatchCommands::ReadChain(const wxString & chain)
124 {
125  // Clear any previous chain
126  ResetChain();
127 
128  // Build the filename
129  wxFileName name(FileNames::ChainDir(), chain, wxT("txt"));
130 
131  // Set the file name
132  wxTextFile tf(name.GetFullPath());
133 
134  // Open and check
135  tf.Open();
136  if (!tf.IsOpened()) {
137  // wxTextFile will display any errors
138  return false;
139  }
140 
141  // Load commands from the file
142  int lines = tf.GetLineCount();
143  if (lines > 0) {
144  for (int i = 0; i < lines; i++) {
145 
146  // Find the command name terminator...ingore line if not found
147  int splitAt = tf[i].Find(wxT(':'));
148  if (splitAt < 0) {
149  continue;
150  }
151 
152  // Parse and clean
153  wxString cmd = tf[i].Left(splitAt).Strip(wxString::both);
154  wxString parm = tf[i].Mid(splitAt + 1).Strip(wxString::trailing);
155 
156  // Backward compatibility for old Chain scripts
157  // Please comment the version of audacity these are introduced in, so
158  // that old ones can easily be removed once users have had a chance to
159  // migrate
160  if (cmd == wxT("SaveMP3_56k_before"))
161  cmd = wxT("ExportMP3_56k_before");
162  else if (cmd == wxT("SaveMP3_56k_after"))
163  cmd = wxT("ExportMP3_56k_after");
164  else if (cmd == wxT("ExportFlac"))
165  cmd = wxT("ExportFLAC");
166  else if (cmd == wxT("ExportMp3"))
167  cmd = wxT("ExportMP3");
168  else if (cmd == wxT("ExportWav"))
169  cmd = wxT("ExportWAV");
170  else if (cmd == wxT("Compressor") && (parm.find(wxT("DecayTime")) != parm.npos))
171  parm.Replace(wxT("DecayTime"), wxT("ReleaseTime"), NULL); // 2.0.6
172 
173  // Add to lists
174  mCommandChain.Add(cmd);
175  mParamsChain.Add(parm);
176  }
177  }
178 
179  // Done with the file
180  tf.Close();
181 
182  return true;
183 }
184 
185 
186 bool BatchCommands::WriteChain(const wxString & chain)
187 {
188  // Build the filename
189  wxFileName name(FileNames::ChainDir(), chain, wxT("txt"));
190 
191  // Set the file name
192  wxTextFile tf(name.GetFullPath());
193 
194  // Create the file (Create() doesn't leave the file open)
195  if (!tf.Exists()) {
196  tf.Create();
197  }
198 
199  // Open it
200  tf.Open();
201 
202  if (!tf.IsOpened()) {
203  // wxTextFile will display any errors
204  return false;
205  }
206 
207  // Start with a clean slate
208  tf.Clear();
209 
210  // Copy over the commands
211  int lines = mCommandChain.GetCount();
212  for (int i = 0; i < lines; i++) {
213  // restore deprecated commands in chain script
214  if (mCommandChain[i] == wxT("ExportMP3_56k_before"))
215  mCommandChain[i] = wxT("SaveMP3_56k_before");
216  else if (mCommandChain[i] == wxT("ExportMP3_56k_after"))
217  mCommandChain[i] = wxT("SaveMP3_56k_after");
218  else if (mCommandChain[i] == wxT("ExportFLAC"))
219  mCommandChain[i] = wxT("ExportFlac");
220  else if (mCommandChain[i] == wxT("ExportMP3"))
221  mCommandChain[i] = wxT("ExportMp3");
222  else if (mCommandChain[i] == wxT("ExportWAV"))
223  mCommandChain[i] = wxT("ExportWav");
224 
225  tf.AddLine(mCommandChain[i] + wxT(":") + mParamsChain[ i ]);
226  }
227 
228  // Write the chain
229  tf.Write();
230 
231  // Done with the file
232  tf.Close();
233 
234  return true;
235 }
236 
237 bool BatchCommands::AddChain(const wxString & chain)
238 {
239  // Build the filename
240  wxFileName name(FileNames::ChainDir(), chain, wxT("txt"));
241 
242  // Set the file name
243  wxTextFile tf(name.GetFullPath());
244 
245  // Create it..Create will display errors
246  return tf.Create();
247 }
248 
249 bool BatchCommands::DeleteChain(const wxString & chain)
250 {
251  // Build the filename
252  wxFileName name(FileNames::ChainDir(), chain, wxT("txt"));
253 
254  // Delete it...wxRemoveFile will display errors
255  return wxRemoveFile(name.GetFullPath());
256 }
257 
258 bool BatchCommands::RenameChain(const wxString & oldchain, const wxString & newchain)
259 {
260  // Build the filenames
261  wxFileName oname(FileNames::ChainDir(), oldchain, wxT("txt"));
262  wxFileName nname(FileNames::ChainDir(), newchain, wxT("txt"));
263 
264  // Rename it...wxRenameFile will display errors
265  return wxRenameFile(oname.GetFullPath(), nname.GetFullPath());
266 }
267 
268 void BatchCommands::SetWavToMp3Chain() // a function per default chain? This is flawed design! MJS
269 {
270  ResetChain();
271 
272  AddToChain( wxT("Normalize") );
273  AddToChain( wxT("ExportMP3") );
274 }
275 
276 // Gets all commands that are valid for this mode.
278 {
279  CommandNameVector commands;
280 
281  AudacityProject *project = GetActiveProject();
282  if (!project)
283  return commands;
284 
285  // CLEANSPEECH remnant
286  for( const auto &command : SpecialCommands )
287  commands.push_back( {
288  //wxGetTranslation
289  (command.first),
290  command.second
291  } );
292 
293  // end CLEANSPEECH remnant
294 
298  while (plug)
299  {
300  auto command = em.GetEffectIdentifier(plug->GetID());
301  if (!command.IsEmpty())
302  commands.push_back( {
303  plug->GetUntranslatedName(), // plug->GetTranslatedName(),
304  command
305  } );
306  plug = pm.GetNextPlugin(PluginTypeEffect);
307  }
308 
309  // Sort commands by their user-visible names.
310  // PRL: What should happen if first members of pairs are not unique?
311  // Sort stably?
312  std::sort(
313  commands.begin(), commands.end(),
314  [](const CommandName &a, const CommandName &b)
315  { return a.first < b.first; }
316  );
317 
318  /* This is for later in development: include the menu commands.
319  CommandManager * mManager = project->GetCommandManager();
320  wxArrayString mNames;
321  mNames.Clear();
322  mManager->GetAllCommandNames(mNames, false);
323  for(i=0; i<mNames.GetCount(); i++) {
324  commands.Add( mNames[i] );
325  }
326  */
327  return commands;
328 }
329 
330 
331 wxString BatchCommands::GetCurrentParamsFor(const wxString & command)
332 {
333  const PluginID & ID = EffectManager::Get().GetEffectByIdentifier(command);
334  if (ID.empty())
335  {
336  return wxEmptyString; // effect not found.
337  }
338 
340 }
341 
342 wxString BatchCommands::PromptForParamsFor(const wxString & command, const wxString & params, wxWindow *parent)
343 {
344  const PluginID & ID = EffectManager::Get().GetEffectByIdentifier(command);
345  if (ID.empty())
346  {
347  return wxEmptyString; // effect not found
348  }
349 
350  wxString res = params;
351 
352  auto cleanup = EffectManager::Get().SetBatchProcessing(ID);
353 
354  if (EffectManager::Get().SetEffectParameters(ID, params))
355  {
356  if (EffectManager::Get().PromptUser(ID, parent))
357  {
359  }
360  }
361 
362  return res;
363 }
364 
365 wxString BatchCommands::PromptForPresetFor(const wxString & command, const wxString & params, wxWindow *parent)
366 {
367  const PluginID & ID = EffectManager::Get().GetEffectByIdentifier(command);
368  if (ID.empty())
369  {
370  return wxEmptyString; // effect not found.
371  }
372 
373  wxString preset = EffectManager::Get().GetPreset(ID, params, parent);
374 
375  // Preset will be empty if the user cancelled the dialog, so return the original
376  // parameter value.
377  if (preset.IsEmpty())
378  {
379  return params;
380  }
381 
382  return preset;
383 }
384 
386 {
387  AudacityProject *project = GetActiveProject();
388  if( project == NULL )
389  {
390  //AudacityMessageBox( _("No project to process!") );
391  return -1.0;
392  }
393  TrackList * tracks = project->GetTracks();
394  if( tracks == NULL )
395  {
396  //AudacityMessageBox( _("No tracks to process!") );
397  return -1.0;
398  }
399 
400  double endTime = tracks->GetEndTime();
401  return endTime;
402 }
403 
405 {
406  AudacityProject *project = GetActiveProject();
407  if( project == NULL )
408  {
409  //AudacityMessageBox( _("No project and no Audio to process!") );
410  return false;
411  }
412 
413  TrackList * tracks = project->GetTracks();
414  if( tracks == NULL )
415  {
416  //AudacityMessageBox( _("No tracks to process!") );
417  return false;
418  }
419 
420  TrackListIterator iter(tracks);
421  Track *t = iter.First();
422  bool mono = true;
423  while (t) {
424  if (t->GetLinked()) {
425  mono = false;
426  break;
427  }
428  t = iter.Next();
429  }
430 
431  return mono;
432 }
433 
434 wxString BatchCommands::BuildCleanFileName(const wxString &fileName, const wxString &extension)
435 {
436  const wxFileName newFileName{ fileName };
437  wxString justName = newFileName.GetName();
438  wxString pathName = newFileName.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR);
439  const auto cleanedString = _("cleaned");
440 
441  if (justName.empty()) {
442  wxDateTime now = wxDateTime::Now();
443  int year = now.GetYear();
444  wxDateTime::Month month = now.GetMonth();
445  wxString monthName = now.GetMonthName(month);
446  int dom = now.GetDay();
447  int hour = now.GetHour();
448  int minute = now.GetMinute();
449  int second = now.GetSecond();
450  justName = wxString::Format(wxT("%d-%s-%02d-%02d-%02d-%02d"),
451  year, monthName, dom, hour, minute, second);
452 
453 // SetName(cleanedFileName);
454 // bool isStereo;
455 // double endTime = project->mTracks->GetEndTime();
456 // double startTime = 0.0;
457  //OnSelectAll();
459  ::AudacityMessageBox(wxString::Format(_("Export recording to %s\n/%s/%s%s"),
460  pathName, cleanedString, justName, extension),
461  _("Export recording"),
462  wxOK | wxCENTRE);
463  pathName += wxFileName::GetPathSeparator();
464  }
465  wxString cleanedName = pathName;
466  cleanedName += cleanedString;
467  bool flag = ::wxFileName::FileExists(cleanedName);
468  if (flag == true) {
469  ::AudacityMessageBox(_("Cannot create directory 'cleaned'. \nFile already exists that is not a directory"));
470  return wxString{};
471  }
472  ::wxFileName::Mkdir(cleanedName, 0777, wxPATH_MKDIR_FULL); // make sure it exists
473 
474  cleanedName += wxFileName::GetPathSeparator();
475  cleanedName += justName;
476  cleanedName += extension;
477  wxGetApp().AddFileToHistory(cleanedName);
478 
479  return cleanedName;
480 }
481 
482 bool BatchCommands::WriteMp3File( const wxString & Name, int bitrate )
483 { //check if current project is mono or stereo
484  unsigned numChannels = 2;
485  if (IsMono()) {
486  numChannels = 1;
487  }
488 
489  double endTime = GetEndTime();
490  if( endTime <= 0.0f )
491  return false;
492  AudacityProject *project = GetActiveProject();
493  if( bitrate <=0 )
494  {
495  // 'No' bitrate given, use the current default.
496  // Use Mp3Stereo to control if export is to a stereo or mono file
497  return mExporter.Process(project, numChannels, wxT("MP3"), Name, false, 0.0, endTime);
498  }
499 
500 
501  bool rc;
502  long prevBitRate = gPrefs->Read(wxT("/FileFormats/MP3Bitrate"), 128);
503  gPrefs->Write(wxT("/FileFormats/MP3Bitrate"), bitrate);
504 
505  auto cleanup = finally( [&] {
506  gPrefs->Write(wxT("/FileFormats/MP3Bitrate"), prevBitRate);
507  gPrefs->Flush();
508  } );
509 
510  // Use Mp3Stereo to control if export is to a stereo or mono file
511  rc = mExporter.Process(project, numChannels, wxT("MP3"), Name, false, 0.0, endTime);
512  return rc;
513 }
514 
515 // TIDY-ME: Get rid of special commands and make them part of the
516 // 'menu' system (but not showing on the menu)
517 //
518 // ======= IMPORTANT ========
519 // Special Commands are a KLUDGE whilst we wait for a better system to handle the menu
520 // commands from batch mode.
521 //
522 // Really we should be using a similar (or same) system to that used for effects
523 // so that parameters can be passed to the commands. Many of the menu
524 // commands take a selection as their parameter.
525 //
526 // If you find yourself adding lots of existing commands from the menus here, STOP
527 // and think again.
528 // ======= IMPORTANT ========
529 // CLEANSPEECH remnant
530 bool BatchCommands::ApplySpecialCommand(int WXUNUSED(iCommand), const wxString & command,const wxString & params)
531 {
532  if (ReportAndSkip(command, params))
533  return true;
534 
535  AudacityProject *project = GetActiveProject();
536 
537  unsigned numChannels = 1; //used to switch between mono and stereo export
538  if (IsMono()) {
539  numChannels = 1; //export in mono
540  } else {
541  numChannels = 2; //export in stereo
542  }
543 
544  wxString filename;
545  wxString extension; // required for correct message
546  if (command == wxT("ExportWAV"))
547  extension = wxT(".wav");
548  else if (command == wxT("ExportOgg"))
549  extension = wxT(".ogg");
550  else if (command == wxT("ExportFLAC"))
551  extension = wxT(".flac");
552  else extension = wxT(".mp3");
553 
554  if (mFileName.IsEmpty()) {
555  filename = BuildCleanFileName(project->GetFileName(), extension);
556  }
557  else {
558  filename = BuildCleanFileName(mFileName, extension);
559  }
560 
561  // We have a command index, but we don't use it!
562  // TODO: Make this special-batch-command code use the menu item code....
563  // FIXME: TRAP_ERR No error reporting on write file failure in batch mode.
564  if (command == wxT("NoAction")) {
565  return true;
566  } else if (!mFileName.IsEmpty() && command == wxT("Import")) {
567  // historically this was in use, now ignored if there
568  return true;
569  } else if (command == wxT("ExportMP3_56k_before")) {
570  filename.Replace(wxT("cleaned/"), wxT("cleaned/MasterBefore_"), false);
571  return WriteMp3File(filename, 56);
572  } else if (command == wxT("ExportMP3_56k_after")) {
573  filename.Replace(wxT("cleaned/"), wxT("cleaned/MasterAfter_"), false);
574  return WriteMp3File(filename, 56);
575  } else if (command == wxT("ExportMP3")) {
576  return WriteMp3File(filename, 0); // 0 bitrate means use default/current
577  } else if (command == wxT("ExportWAV")) {
578  filename.Replace(wxT(".mp3"), wxT(".wav"), false);
579  double endTime = GetEndTime();
580  if (endTime <= 0.0f) {
581  return false;
582  }
583  return mExporter.Process(project, numChannels, wxT("WAV"), filename, false, 0.0, endTime);
584  } else if (command == wxT("ExportOgg")) {
585 #ifdef USE_LIBVORBIS
586  filename.Replace(wxT(".mp3"), wxT(".ogg"), false);
587  double endTime = GetEndTime();
588  if (endTime <= 0.0f) {
589  return false;
590  }
591  return mExporter.Process(project, numChannels, wxT("OGG"), filename, false, 0.0, endTime);
592 #else
593  AudacityMessageBox(_("Ogg Vorbis support is not included in this build of Audacity"));
594  return false;
595 #endif
596  } else if (command == wxT("ExportFLAC")) {
597 #ifdef USE_LIBFLAC
598  filename.Replace(wxT(".mp3"), wxT(".flac"), false);
599  double endTime = GetEndTime();
600  if (endTime <= 0.0f) {
601  return false;
602  }
603  return mExporter.Process(project, numChannels, wxT("FLAC"), filename, false, 0.0, endTime);
604 #else
605  AudacityMessageBox(_("FLAC support is not included in this build of Audacity"));
606  return false;
607 #endif
608  }
609  AudacityMessageBox(wxString::Format(_("Command %s not implemented yet"),command));
610  return false;
611 }
612 // end CLEANSPEECH remnant
613 
614 bool BatchCommands::ApplyEffectCommand(const PluginID & ID, const wxString & command, const wxString & params)
615 {
616  //Possibly end processing here, if in batch-debug
617  if( ReportAndSkip(command, params))
618  return true;
619 
620  AudacityProject *project = GetActiveProject();
621 
622  // FIXME: for later versions may want to not select-all in batch mode.
623  // IF nothing selected, THEN select everything
624  // (most effects require that you have something selected).
625  project->SelectAllIfNone();
626 
627  bool res = false;
628 
629  auto cleanup = EffectManager::Get().SetBatchProcessing(ID);
630 
631  // transfer the parameters to the effect...
632  if (EffectManager::Get().SetEffectParameters(ID, params))
633  {
634  // and apply the effect...
638  }
639 
640  return res;
641 }
642 
643 bool BatchCommands::ApplyCommand(const wxString & command, const wxString & params)
644 {
645 
646  unsigned int i;
647  // Test for a special command.
648  // CLEANSPEECH remnant
649  for( i = 0; i < sizeof(SpecialCommands)/sizeof(*SpecialCommands); ++i ) {
650  if( command == SpecialCommands[i].second )
651  return ApplySpecialCommand( i, command, params );
652  }
653  // end CLEANSPEECH remnant
654 
655  // Test for an effect.
656  const PluginID & ID = EffectManager::Get().GetEffectByIdentifier( command );
657  if (!ID.empty())
658  {
659  return ApplyEffectCommand(ID, command, params);
660  }
661 
663  wxString::Format(
664  _("Your batch command of %s was not recognized."), command ));
665 
666  return false;
667 }
668 
669 bool BatchCommands::ApplyCommandInBatchMode(const wxString & command, const wxString &params)
670 {
671  AudacityProject *project = GetActiveProject();
672 
673  // enter batch mode...
674  bool prevShowMode = project->GetShowId3Dialog();
675  auto cleanup = finally( [&] {
676  // exit batch mode...
677  project->SetShowId3Dialog(prevShowMode);
678  } );
679 
680  return ApplyCommand( command, params );
681 }
682 
683 // ApplyChain returns true on success, false otherwise.
684 // Any error reporting to the user has already been done.
685 bool BatchCommands::ApplyChain(const wxString & filename)
686 {
687  mFileName = filename;
688 
690  bool res = false;
691  auto cleanup = finally( [&] {
692  if (!res) {
693  if(proj) {
694  // Chain failed or was cancelled; revert to the previous state
695  proj->RollbackState();
696  }
697  }
698  } );
699 
700  mAbort = false;
701 
702  size_t i = 0;
703  for (; i < mCommandChain.GetCount(); i++) {
705  break;
706  }
707 
708  res = (i == mCommandChain.GetCount());
709  if (!res)
710  return false;
711 
712  mFileName.Empty();
713 
714  // Chain was successfully applied; save the NEW project state
715  wxString longDesc, shortDesc;
716  wxString name = gPrefs->Read(wxT("/Batch/ActiveChain"), wxEmptyString);
717  if (name.IsEmpty())
718  {
719  /* i18n-hint: active verb in past tense */
720  longDesc = _("Applied batch chain");
721  shortDesc = _("Apply chain");
722  }
723  else
724  {
725  /* i18n-hint: active verb in past tense */
726  longDesc = wxString::Format(_("Applied batch chain '%s'"), name);
727  shortDesc = wxString::Format(_("Apply '%s'"), name);
728  }
729 
730  if (!proj)
731  return false;
732  proj->PushState(longDesc, shortDesc);
733  return true;
734 }
735 
736 // AbortBatch() allows a premature terminatation of a batch.
738 {
739  mAbort = true;
740 }
741 
742 void BatchCommands::AddToChain(const wxString &command, int before)
743 {
744  AddToChain(command, GetCurrentParamsFor(command), before);
745 }
746 
747 void BatchCommands::AddToChain(const wxString &command, const wxString &params, int before)
748 {
749  if (before == -1) {
750  before = (int)mCommandChain.GetCount();
751  }
752 
753  mCommandChain.Insert(command, before);
754  mParamsChain.Insert(params, before);
755 }
756 
758 {
759  if (index < 0 || index >= (int)mCommandChain.GetCount()) {
760  return;
761  }
762 
763  mCommandChain.RemoveAt(index);
764  mParamsChain.RemoveAt(index);
765 }
766 
768 {
769  mCommandChain.Clear();
770  mParamsChain.Clear();
771 }
772 
773 // ReportAndSkip() is a diagnostic function that avoids actually
774 // applying the requested effect if in batch-debug mode.
775 bool BatchCommands::ReportAndSkip(const wxString & command, const wxString & params)
776 {
777  int bDebug;
778  gPrefs->Read(wxT("/Batch/Debug"), &bDebug, false);
779  if( bDebug == 0 )
780  return false;
781 
782  //TODO: Add a cancel button to these, and add the logic so that we can abort.
783  if( params != wxT("") )
784  {
785  AudacityMessageBox( wxString::Format(_("Apply %s with parameter(s)\n\n%s"),command, params),
786  _("Test Mode"));
787  }
788  else
789  {
790  AudacityMessageBox( wxString::Format(_("Apply %s"),command),
791  _("Test Mode"));
792  }
793  return true;
794 }
795 
796 wxArrayString BatchCommands::GetNames()
797 {
798  wxArrayString names;
799  wxArrayString files;
800  wxDir::GetAllFiles(FileNames::ChainDir(), &files, wxT("*.txt"), wxDIR_FILES);
801  size_t i;
802 
803  wxFileName ff;
804  for (i = 0; i < files.GetCount(); i++) {
805  ff = (files[i]);
806  names.Add(ff.GetName());
807  }
808 
809  return names;
810 }
811 
812 bool BatchCommands::IsFixed(const wxString & name)
813 {
814  if (name == MP3Conversion)
815  return true;
816  return false;
817 }
818 
819 void BatchCommands::RestoreChain(const wxString & name)
820 {
821 // TIDY-ME: Effects change their name with localisation.
822 // Commands (at least currently) don't. Messy.
823 
824  if (name == MP3Conversion)
826 }
827 
828 void BatchCommands::Split(const wxString & str, wxString & command, wxString & param)
829 {
830  int splitAt;
831 
832  command.Empty();
833  param.Empty();
834 
835  if (str.IsEmpty()) {
836  return;
837  }
838 
839  splitAt = str.Find(wxT(':'));
840  if (splitAt < 0) {
841  return;
842  }
843 
844  command = str.Mid(0, splitAt);
845  param = str.Mid(splitAt + 1);
846 
847  return;
848 }
849 
850 wxString BatchCommands::Join(const wxString & command, const wxString & param)
851 {
852  return command + wxT(": ") + param;
853 }
wxArrayString mParamsChain
Definition: BatchCommands.h:82
bool ReadChain(const wxString &chain)
static wxString PromptForParamsFor(const wxString &command, const wxString &params, wxWindow *parent)
static wxString FindDefaultPath(Operation op)
Definition: FileNames.cpp:384
wxString GetCommand(int index)
static const std::pair< const wxChar *, const wxChar * > SpecialCommands[]
static wxArrayString names()
Definition: Tags.cpp:697
A list of TrackListNode items.
Definition: Track.h:553
static const int kConfigured
Definition: Project.h:478
static const wxString MP3Conversion
static const int kDontRepeatLast
Definition: Project.h:482
bool ApplyCommand(const wxString &command, const wxString &params)
void SetWavToMp3Chain()
double GetEndTime() const
Definition: Track.cpp:1334
Exporter mExporter
Definition: BatchCommands.h:86
void AddToChain(const wxString &command, int before=-1)
const PluginID & GetEffectByIdentifier(const wxString &strTarget)
bool Process(AudacityProject *project, bool selectedOnly, double t0, double t1)
Definition: Export.cpp:344
std::vector< CommandName > CommandNameVector
Definition: BatchCommands.h:46
bool GetLinked() const
Definition: Track.h:218
double GetEndTime()
void SetShowId3Dialog(bool flag)
Definition: Project.h:302
bool WriteChain(const wxString &chain)
#define XO(s)
Definition: Internat.h:30
int AudacityMessageBox(const wxString &message, const wxString &caption=AudacityMessageBoxCaptionStr(), long style=wxOK|wxCENTRE, wxWindow *parent=NULL, int x=wxDefaultCoord, int y=wxDefaultCoord)
Definition: ErrorDialog.h:92
wxString mFileName
Definition: BatchCommands.h:87
static wxString PromptForPresetFor(const wxString &command, const wxString &params, wxWindow *parent)
bool RenameChain(const wxString &oldchain, const wxString &newchain)
bool ApplyCommandInBatchMode(const wxString &command, const wxString &params)
wxString mMessage
Definition: BatchCommands.h:84
wxString GetEffectIdentifier(const PluginID &ID)
wxString Join(const wxString &command, const wxString &param)
void AddFileToHistory(const wxString &name)
AudacityProject provides the main window, with tools and tracks contained within it.
Definition: Project.h:161
wxString GetParams(int index)
wxFileConfig * gPrefs
Definition: Prefs.cpp:72
bool ApplyEffectCommand(const PluginID &ID, const wxString &command, const wxString &params)
bool ApplySpecialCommand(int iCommand, const wxString &command, const wxString &params)
const PluginDescriptor * GetNextPlugin(PluginType type)
wxString BuildCleanFileName(const wxString &fileName, const wxString &extension)
static wxString ChainDir()
Definition: FileNames.cpp:193
static wxArrayString GetNames()
void RollbackState()
Definition: Project.cpp:4526
const PluginDescriptor * GetFirstPlugin(PluginType type)
wxString GetUntranslatedName() const
static CommandNameVector GetAllCommands()
static const int kSkipState
Definition: Project.h:480
bool GetShowId3Dialog()
Definition: Project.h:301
Fundamental data object of Audacity, placed in the TrackPanel. Classes derived form it include the Wa...
Definition: Track.h:67
EffectManager is the class that handles effects and effect categories.
Definition: EffectManager.h:49
void Split(const wxString &str, wxString &command, wxString &param)
bool DeleteChain(const wxString &name)
virtual Track * First(TrackList *val=nullptr)
Definition: Track.cpp:355
bool ApplyChain(const wxString &filename=wxT(""))
static EffectManager & Get()
wxString GetPreset(const PluginID &ID, const wxString &params, wxWindow *parent)
wxArrayString mCommandChain
Definition: BatchCommands.h:81
bool DoEffect(const PluginID &ID, int flags)
Definition: Menus.cpp:4328
An iterator for a TrackList.
Definition: Track.h:339
_("Move Track &Down")+wxT("\t")+(GetActiveProject() -> GetCommandManager() ->GetKeyFromName(wxT("TrackMoveDown"))), OnMoveTrack) POPUP_MENU_ITEM(OnMoveTopID, _("Move Track to &Top")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveTop"))), OnMoveTrack) POPUP_MENU_ITEM(OnMoveBottomID, _("Move Track to &Bottom")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveBottom"))), OnMoveTrack) void TrackMenuTable::OnSetName(wxCommandEvent &)
wxString GetEffectParameters(const PluginID &ID)
bool ReportAndSkip(const wxString &command, const wxString &params)
void PushState(const wxString &desc, const wxString &shortDesc)
Definition: Project.cpp:4486
const wxChar * name
Definition: Distortion.cpp:94
const wxString & GetID() const
virtual Track * Next(bool skiplinked=false)
Definition: Track.cpp:396
AUDACITY_DLL_API AudacityProject * GetActiveProject()
Definition: Project.cpp:302
void DeleteFromChain(int index)
bool IsFixed(const wxString &name)
AudacityApp & wxGetApp()
void RestoreChain(const wxString &name)
TrackList * GetTracks()
Definition: Project.h:177
static PluginManager & Get()
eCommandType
bool WriteMp3File(const wxString &Name, int bitrate)
EffectDistortion::Params params
Definition: Distortion.cpp:95
static wxString GetCurrentParamsFor(const wxString &command)
const wxString & GetFileName()
Definition: Project.h:287
bool AddChain(const wxString &chain)
void SetBatchProcessing(const PluginID &ID, bool start)
void SelectAllIfNone()
Definition: Menus.cpp:2212