2021-05-09 15:16:56 +00:00
|
|
|
|
2018-11-11 17:27:44 +00:00
|
|
|
|
Command flag functions out of Menus.cpp, reducing its dependencies...
... Mostly into CommonCommandFlags.cpp, but some elsewhere, to avoid giving
that new file problematic dependencies on LabelTrack, ControlToolBar, and
EffectManager.
Note that CutCopyAvailableFlag is critically ordered, for message purposes,
only with AudioIONotAvailableFlag, the only flag with a message that it combines
with in menu item definitions.
The dependency on LabelTrack.cpp might not be a bad one later, if the track and
its view can be separated, and that would allow CutCopyAvailableFlag to be
put with the others. But much other work on LabelTrack must happen first.
2019-06-14 15:39:12 +00:00
|
|
|
#include "../CommonCommandFlags.h"
|
2018-10-22 03:14:14 +00:00
|
|
|
#include "../FileNames.h"
|
|
|
|
#include "../LabelTrack.h"
|
|
|
|
#include "../NoteTrack.h"
|
|
|
|
#include "../Prefs.h"
|
|
|
|
#include "../Printing.h"
|
|
|
|
#include "../Project.h"
|
2020-07-01 05:45:17 +00:00
|
|
|
#include "../ProjectFileIO.h"
|
2019-06-09 14:25:01 +00:00
|
|
|
#include "../ProjectFileManager.h"
|
2019-06-06 13:55:34 +00:00
|
|
|
#include "../ProjectHistory.h"
|
2019-05-29 15:42:31 +00:00
|
|
|
#include "../ProjectManager.h"
|
2019-05-29 16:05:22 +00:00
|
|
|
#include "../ProjectWindow.h"
|
2019-06-21 23:38:38 +00:00
|
|
|
#include "../SelectUtilities.h"
|
2019-04-21 21:01:31 +00:00
|
|
|
#include "../TrackPanel.h"
|
2020-07-26 07:32:41 +00:00
|
|
|
#include "../UndoManager.h"
|
2019-04-28 10:49:47 +00:00
|
|
|
#include "../ViewInfo.h"
|
2018-10-22 03:14:14 +00:00
|
|
|
#include "../WaveTrack.h"
|
|
|
|
#include "../commands/CommandContext.h"
|
|
|
|
#include "../commands/CommandManager.h"
|
2020-08-10 22:48:59 +00:00
|
|
|
#include "../export/ExportMP3.h"
|
2018-10-22 03:14:14 +00:00
|
|
|
#include "../export/ExportMultiple.h"
|
2019-12-20 18:02:31 +00:00
|
|
|
#include "../import/Import.h"
|
2019-06-25 02:31:11 +00:00
|
|
|
#include "../import/ImportMIDI.h"
|
2020-06-13 15:34:59 +00:00
|
|
|
#include "../import/ImportRaw.h"
|
2019-05-20 18:27:11 +00:00
|
|
|
#include "../widgets/AudacityMessageBox.h"
|
2019-03-30 19:22:43 +00:00
|
|
|
#include "../widgets/FileHistory.h"
|
2020-08-05 14:55:07 +00:00
|
|
|
#include "../widgets/wxPanelWrapper.h"
|
2018-10-22 03:14:14 +00:00
|
|
|
|
|
|
|
#ifdef USE_MIDI
|
|
|
|
#include "../import/ImportMIDI.h"
|
|
|
|
#endif // USE_MIDI
|
|
|
|
|
2019-03-23 14:53:24 +00:00
|
|
|
#include <wx/menu.h>
|
|
|
|
|
2018-10-22 03:14:14 +00:00
|
|
|
// private helper classes and functions
|
|
|
|
namespace {
|
2020-08-10 22:48:59 +00:00
|
|
|
|
2020-08-12 13:12:46 +00:00
|
|
|
void DoExport(AudacityProject &project, const FileExtension &format)
|
2018-10-22 03:14:14 +00:00
|
|
|
{
|
2019-05-06 23:00:10 +00:00
|
|
|
auto &tracks = TrackList::Get( project );
|
2020-07-01 05:45:17 +00:00
|
|
|
auto &projectFileIO = ProjectFileIO::Get( project );
|
|
|
|
|
2019-05-22 00:16:20 +00:00
|
|
|
Exporter e{ project };
|
2018-10-22 03:14:14 +00:00
|
|
|
|
|
|
|
double t0 = 0.0;
|
2019-05-06 23:00:10 +00:00
|
|
|
double t1 = tracks.GetEndTime();
|
2020-08-10 22:48:59 +00:00
|
|
|
wxString projectName = project.GetProjectName();
|
2018-10-22 03:14:14 +00:00
|
|
|
|
|
|
|
// Prompt for file name and/or extension?
|
2020-08-10 22:48:59 +00:00
|
|
|
bool bPromptingRequired = !project.mBatchMode ||
|
|
|
|
projectName.empty() ||
|
|
|
|
format.empty();
|
2018-10-22 03:14:14 +00:00
|
|
|
|
2020-08-10 22:48:59 +00:00
|
|
|
bool success = false;
|
|
|
|
if (bPromptingRequired) {
|
2018-10-22 03:14:14 +00:00
|
|
|
// Do export with prompting.
|
2020-08-10 22:48:59 +00:00
|
|
|
e.SetDefaultFormat(format);
|
|
|
|
success = e.Process(false, t0, t1);
|
2018-10-22 03:14:14 +00:00
|
|
|
}
|
2020-08-10 22:48:59 +00:00
|
|
|
else {
|
2021-04-09 18:05:19 +00:00
|
|
|
// We either use a configured output path,
|
|
|
|
// or we use the default documents folder - just as for exports.
|
|
|
|
FilePath pathName = FileNames::FindDefaultPath(FileNames::Operation::MacrosOut);
|
|
|
|
/*
|
2020-08-10 22:48:59 +00:00
|
|
|
// If we've gotten to this point, we are in batch mode, have a file format,
|
|
|
|
// and the project has either been saved or a file has been imported. So, we
|
|
|
|
// want to use the project's path if it has been saved, otherwise use the
|
|
|
|
// initial import path.
|
|
|
|
FilePath pathName = !projectFileIO.IsTemporary() ?
|
|
|
|
wxPathOnly(projectFileIO.GetFileName()) :
|
|
|
|
project.GetInitialImportPath();
|
2021-04-09 18:05:19 +00:00
|
|
|
*/
|
2020-08-12 13:12:46 +00:00
|
|
|
wxFileName fileName(pathName, projectName, format.Lower());
|
2020-08-10 22:48:59 +00:00
|
|
|
|
|
|
|
// Append the "macro-output" directory to the path
|
|
|
|
const wxString macroDir( "macro-output" );
|
|
|
|
if (fileName.GetDirs().back() != macroDir) {
|
|
|
|
fileName.AppendDir(macroDir);
|
|
|
|
}
|
|
|
|
|
|
|
|
wxString justName = fileName.GetName();
|
|
|
|
wxString extension = fileName.GetExt();
|
|
|
|
FilePath fullPath = fileName.GetFullPath();
|
|
|
|
|
|
|
|
if (wxFileName::FileExists(fileName.GetPath())) {
|
|
|
|
AudacityMessageBox(
|
|
|
|
XO("Cannot create directory '%s'. \n"
|
|
|
|
"File already exists that is not a directory"),
|
|
|
|
Verbatim(fullPath));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
fileName.Mkdir(0777, wxPATH_MKDIR_FULL); // make sure it exists
|
|
|
|
|
|
|
|
int nChannels = (tracks.Any() - &Track::IsLeader ).empty() ? 1 : 2;
|
|
|
|
|
2018-10-22 03:14:14 +00:00
|
|
|
// We're in batch mode, the file does not exist already.
|
|
|
|
// We really can proceed without prompting.
|
2020-08-10 22:48:59 +00:00
|
|
|
success = e.Process(
|
2018-10-22 03:14:14 +00:00
|
|
|
nChannels, // numChannels,
|
2020-08-10 22:48:59 +00:00
|
|
|
format, // type,
|
|
|
|
fullPath, // full path,
|
2018-10-22 03:14:14 +00:00
|
|
|
false, // selectedOnly,
|
|
|
|
t0, // t0
|
|
|
|
t1 // t1
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2020-08-10 22:48:59 +00:00
|
|
|
if (success && !project.mBatchMode) {
|
|
|
|
FileHistory::Global().Append(e.GetAutoExportFileName().GetFullPath());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-13 00:56:41 +00:00
|
|
|
void DoImport(const CommandContext &context, bool isRaw)
|
|
|
|
{
|
|
|
|
auto &project = context.project;
|
|
|
|
auto &trackFactory = WaveTrackFactory::Get( project );
|
|
|
|
auto &window = ProjectWindow::Get( project );
|
|
|
|
|
|
|
|
auto selectedFiles = ProjectFileManager::ShowOpenDialog(FileNames::Operation::Import);
|
|
|
|
if (selectedFiles.size() == 0) {
|
|
|
|
Importer::SetLastOpenType({});
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// PRL: This affects FFmpegImportPlugin::Open which resets the preference
|
|
|
|
// to false. Should it also be set to true on other paths that reach
|
|
|
|
// AudacityProject::Import ?
|
|
|
|
gPrefs->Write(wxT("/NewImportingSession"), true);
|
|
|
|
|
|
|
|
selectedFiles.Sort(FileNames::CompareNoCase);
|
|
|
|
|
|
|
|
auto cleanup = finally( [&] {
|
|
|
|
|
|
|
|
Importer::SetLastOpenType({});
|
|
|
|
window.ZoomAfterImport(nullptr);
|
|
|
|
window.HandleResize(); // Adjust scrollers for NEW track sizes.
|
|
|
|
} );
|
|
|
|
|
|
|
|
for (size_t ff = 0; ff < selectedFiles.size(); ff++) {
|
|
|
|
wxString fileName = selectedFiles[ff];
|
|
|
|
|
|
|
|
FileNames::UpdateDefaultPath(FileNames::Operation::Import, ::wxPathOnly(fileName));
|
|
|
|
|
|
|
|
if (isRaw) {
|
|
|
|
TrackHolders newTracks;
|
|
|
|
|
|
|
|
::ImportRaw(project, &window, fileName, &trackFactory, newTracks);
|
|
|
|
|
|
|
|
if (newTracks.size() > 0) {
|
|
|
|
ProjectFileManager::Get( project )
|
|
|
|
.AddImportedTracks(fileName, std::move(newTracks));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
ProjectFileManager::Get( project ).Import(fileName);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-22 03:14:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Menu handler functions
|
|
|
|
|
2019-06-25 02:31:11 +00:00
|
|
|
namespace FileActions {
|
|
|
|
|
2018-10-22 03:14:14 +00:00
|
|
|
struct Handler : CommandHandlerObject {
|
|
|
|
|
2018-10-29 17:35:56 +00:00
|
|
|
void OnNew(const CommandContext & )
|
2018-10-22 03:14:14 +00:00
|
|
|
{
|
2019-04-29 06:22:08 +00:00
|
|
|
( void ) ProjectManager::New();
|
2018-10-22 03:14:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void OnOpen(const CommandContext &context )
|
|
|
|
{
|
|
|
|
auto &project = context.project;
|
2019-04-29 06:22:08 +00:00
|
|
|
ProjectManager::OpenFiles(&project);
|
2018-10-22 03:14:14 +00:00
|
|
|
}
|
|
|
|
|
2020-04-11 07:08:33 +00:00
|
|
|
// JKC: This is like OnClose, except it empties the project in place,
|
|
|
|
// rather than creating a new empty project (with new toolbars etc).
|
2018-10-22 03:14:14 +00:00
|
|
|
// It does not test for unsaved changes.
|
|
|
|
// It is not in the menus by default. Its main purpose is/was for
|
|
|
|
// developers checking functionality of ResetProjectToEmpty().
|
|
|
|
void OnProjectReset(const CommandContext &context)
|
|
|
|
{
|
|
|
|
auto &project = context.project;
|
2019-04-29 06:22:08 +00:00
|
|
|
ProjectManager::Get( project ).ResetProjectToEmpty();
|
2018-10-22 03:14:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void OnClose(const CommandContext &context )
|
|
|
|
{
|
|
|
|
auto &project = context.project;
|
2019-04-29 06:22:08 +00:00
|
|
|
auto &window = ProjectWindow::Get( project );
|
2019-06-08 20:05:22 +00:00
|
|
|
ProjectFileManager::Get( project ).SetMenuClose(true);
|
2019-05-28 17:12:56 +00:00
|
|
|
window.Close();
|
2018-10-22 03:14:14 +00:00
|
|
|
}
|
|
|
|
|
2020-07-26 07:01:37 +00:00
|
|
|
void OnCompact(const CommandContext &context)
|
2020-07-15 06:32:48 +00:00
|
|
|
{
|
2020-11-17 22:09:41 +00:00
|
|
|
ProjectFileManager::Get(context.project).Compact();
|
2020-07-15 06:32:48 +00:00
|
|
|
}
|
|
|
|
|
2018-10-22 03:14:14 +00:00
|
|
|
void OnSave(const CommandContext &context )
|
|
|
|
{
|
|
|
|
auto &project = context.project;
|
2019-06-07 17:24:38 +00:00
|
|
|
auto &projectFileManager = ProjectFileManager::Get( project );
|
|
|
|
projectFileManager.Save();
|
2018-10-22 03:14:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void OnSaveAs(const CommandContext &context )
|
|
|
|
{
|
|
|
|
auto &project = context.project;
|
2019-06-07 17:24:38 +00:00
|
|
|
auto &projectFileManager = ProjectFileManager::Get( project );
|
|
|
|
projectFileManager.SaveAs();
|
2018-10-22 03:14:14 +00:00
|
|
|
}
|
|
|
|
|
2020-07-03 19:38:57 +00:00
|
|
|
void OnSaveCopy(const CommandContext &context )
|
|
|
|
{
|
|
|
|
auto &project = context.project;
|
|
|
|
auto &projectFileManager = ProjectFileManager::Get( project );
|
|
|
|
projectFileManager.SaveCopy();
|
|
|
|
}
|
|
|
|
|
2018-10-22 03:14:14 +00:00
|
|
|
void OnExportMp3(const CommandContext &context)
|
|
|
|
{
|
|
|
|
auto &project = context.project;
|
|
|
|
DoExport(project, "MP3");
|
|
|
|
}
|
|
|
|
|
|
|
|
void OnExportWav(const CommandContext &context)
|
|
|
|
{
|
|
|
|
auto &project = context.project;
|
|
|
|
DoExport(project, "WAV");
|
|
|
|
}
|
|
|
|
|
|
|
|
void OnExportOgg(const CommandContext &context)
|
|
|
|
{
|
|
|
|
auto &project = context.project;
|
|
|
|
DoExport(project, "OGG");
|
|
|
|
}
|
|
|
|
|
|
|
|
void OnExportAudio(const CommandContext &context)
|
|
|
|
{
|
|
|
|
auto &project = context.project;
|
|
|
|
DoExport(project, "");
|
|
|
|
}
|
|
|
|
|
|
|
|
void OnExportSelection(const CommandContext &context)
|
|
|
|
{
|
|
|
|
auto &project = context.project;
|
2019-04-28 10:49:47 +00:00
|
|
|
auto &selectedRegion = ViewInfo::Get( project ).selectedRegion;
|
2019-05-22 00:16:20 +00:00
|
|
|
Exporter e{ project };
|
2018-10-22 03:14:14 +00:00
|
|
|
|
2019-12-20 17:13:39 +00:00
|
|
|
e.SetFileDialogTitle( XO("Export Selected Audio") );
|
2019-05-22 00:16:20 +00:00
|
|
|
e.Process(true, selectedRegion.t0(),
|
2018-10-22 03:14:14 +00:00
|
|
|
selectedRegion.t1());
|
|
|
|
}
|
|
|
|
|
|
|
|
void OnExportLabels(const CommandContext &context)
|
|
|
|
{
|
|
|
|
auto &project = context.project;
|
2019-05-06 23:00:10 +00:00
|
|
|
auto &tracks = TrackList::Get( project );
|
2019-05-28 17:12:56 +00:00
|
|
|
auto &window = GetProjectFrame( project );
|
2018-10-22 03:14:14 +00:00
|
|
|
|
|
|
|
/* i18n-hint: filename containing exported text from label tracks */
|
|
|
|
wxString fName = _("labels.txt");
|
2019-05-06 23:00:10 +00:00
|
|
|
auto trackRange = tracks.Any<const LabelTrack>();
|
2018-10-22 03:14:14 +00:00
|
|
|
auto numLabelTracks = trackRange.size();
|
|
|
|
|
|
|
|
if (numLabelTracks == 0) {
|
2019-12-07 19:30:07 +00:00
|
|
|
AudacityMessageBox( XO("There are no label tracks to export.") );
|
2018-10-22 03:14:14 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
fName = (*trackRange.rbegin())->GetName();
|
|
|
|
|
|
|
|
fName = FileNames::SelectFile(FileNames::Operation::Export,
|
2019-12-27 03:48:00 +00:00
|
|
|
XO("Export Labels As:"),
|
|
|
|
wxEmptyString,
|
|
|
|
fName,
|
|
|
|
wxT("txt"),
|
|
|
|
{ FileNames::TextFiles },
|
|
|
|
wxFD_SAVE | wxFD_OVERWRITE_PROMPT | wxRESIZE_BORDER,
|
|
|
|
&window);
|
2018-10-22 03:14:14 +00:00
|
|
|
|
2019-03-14 17:04:37 +00:00
|
|
|
if (fName.empty())
|
2018-10-22 03:14:14 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
// Move existing files out of the way. Otherwise wxTextFile will
|
|
|
|
// append to (rather than replace) the current file.
|
|
|
|
|
|
|
|
if (wxFileExists(fName)) {
|
|
|
|
#ifdef __WXGTK__
|
|
|
|
wxString safetyFileName = fName + wxT("~");
|
|
|
|
#else
|
|
|
|
wxString safetyFileName = fName + wxT(".bak");
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (wxFileExists(safetyFileName))
|
|
|
|
wxRemoveFile(safetyFileName);
|
|
|
|
|
|
|
|
wxRename(fName, safetyFileName);
|
|
|
|
}
|
|
|
|
|
|
|
|
wxTextFile f(fName);
|
|
|
|
f.Create();
|
|
|
|
f.Open();
|
|
|
|
if (!f.IsOpened()) {
|
2019-12-07 19:30:07 +00:00
|
|
|
AudacityMessageBox(
|
|
|
|
XO( "Couldn't write to file: %s" ).Format( fName ) );
|
2018-10-22 03:14:14 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (auto lt : trackRange)
|
|
|
|
lt->Export(f);
|
|
|
|
|
|
|
|
f.Write();
|
|
|
|
f.Close();
|
|
|
|
}
|
|
|
|
|
|
|
|
void OnExportMultiple(const CommandContext &context)
|
|
|
|
{
|
|
|
|
auto &project = context.project;
|
2019-12-06 10:39:07 +00:00
|
|
|
ExportMultipleDialog em(&project);
|
2018-10-22 03:14:14 +00:00
|
|
|
|
|
|
|
em.ShowModal();
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef USE_MIDI
|
|
|
|
void OnExportMIDI(const CommandContext &context)
|
|
|
|
{
|
|
|
|
auto &project = context.project;
|
2019-05-06 23:00:10 +00:00
|
|
|
auto &tracks = TrackList::Get( project );
|
2019-05-28 17:12:56 +00:00
|
|
|
auto &window = GetProjectFrame( project );
|
2018-10-22 03:14:14 +00:00
|
|
|
|
|
|
|
// Make sure that there is
|
|
|
|
// exactly one NoteTrack selected.
|
2019-05-06 23:00:10 +00:00
|
|
|
const auto range = tracks.Selected< const NoteTrack >();
|
2018-10-22 03:14:14 +00:00
|
|
|
const auto numNoteTracksSelected = range.size();
|
|
|
|
|
|
|
|
if(numNoteTracksSelected > 1) {
|
2019-12-07 19:30:07 +00:00
|
|
|
AudacityMessageBox(
|
|
|
|
XO("Please select only one Note Track at a time.") );
|
2018-10-22 03:14:14 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if(numNoteTracksSelected < 1) {
|
2019-12-07 19:30:07 +00:00
|
|
|
AudacityMessageBox(
|
|
|
|
XO("Please select a Note Track.") );
|
2018-10-22 03:14:14 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
wxASSERT(numNoteTracksSelected);
|
|
|
|
if (!numNoteTracksSelected)
|
|
|
|
return;
|
|
|
|
|
|
|
|
const auto nt = *range.begin();
|
|
|
|
|
|
|
|
while(true) {
|
|
|
|
|
2019-03-15 18:41:21 +00:00
|
|
|
wxString fName;
|
2018-10-22 03:14:14 +00:00
|
|
|
|
|
|
|
fName = FileNames::SelectFile(FileNames::Operation::Export,
|
2019-12-18 21:32:21 +00:00
|
|
|
XO("Export MIDI As:"),
|
2018-10-22 03:14:14 +00:00
|
|
|
wxEmptyString,
|
|
|
|
fName,
|
2019-12-27 16:44:58 +00:00
|
|
|
wxT("mid"),
|
2019-12-27 03:48:00 +00:00
|
|
|
{
|
|
|
|
{ XO("MIDI file"), { wxT("mid") }, true },
|
|
|
|
{ XO("Allegro file"), { wxT("gro") }, true },
|
|
|
|
},
|
2018-10-22 03:14:14 +00:00
|
|
|
wxFD_SAVE | wxFD_OVERWRITE_PROMPT | wxRESIZE_BORDER,
|
2019-05-28 17:12:56 +00:00
|
|
|
&window);
|
2018-10-22 03:14:14 +00:00
|
|
|
|
2019-03-14 17:04:37 +00:00
|
|
|
if (fName.empty())
|
2018-10-22 03:14:14 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
if(!fName.Contains(wxT("."))) {
|
|
|
|
fName = fName + wxT(".mid");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Move existing files out of the way. Otherwise wxTextFile will
|
|
|
|
// append to (rather than replace) the current file.
|
|
|
|
|
|
|
|
if (wxFileExists(fName)) {
|
|
|
|
#ifdef __WXGTK__
|
|
|
|
wxString safetyFileName = fName + wxT("~");
|
|
|
|
#else
|
|
|
|
wxString safetyFileName = fName + wxT(".bak");
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (wxFileExists(safetyFileName))
|
|
|
|
wxRemoveFile(safetyFileName);
|
|
|
|
|
|
|
|
wxRename(fName, safetyFileName);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(fName.EndsWith(wxT(".mid")) || fName.EndsWith(wxT(".midi"))) {
|
|
|
|
nt->ExportMIDI(fName);
|
|
|
|
} else if(fName.EndsWith(wxT(".gro"))) {
|
|
|
|
nt->ExportAllegro(fName);
|
|
|
|
} else {
|
2019-12-07 19:30:07 +00:00
|
|
|
auto msg = XO(
|
|
|
|
"You have selected a filename with an unrecognized file extension.\nDo you want to continue?");
|
|
|
|
auto title = XO("Export MIDI");
|
|
|
|
int id = AudacityMessageBox( msg, title, wxYES_NO );
|
2018-10-22 03:14:14 +00:00
|
|
|
if (id == wxNO) {
|
|
|
|
continue;
|
|
|
|
} else if (id == wxYES) {
|
|
|
|
nt->ExportMIDI(fName);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif // USE_MIDI
|
|
|
|
|
|
|
|
void OnImport(const CommandContext &context)
|
|
|
|
{
|
2021-02-13 00:56:41 +00:00
|
|
|
DoImport(context, false);
|
2018-10-22 03:14:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void OnImportLabels(const CommandContext &context)
|
|
|
|
{
|
|
|
|
auto &project = context.project;
|
2020-08-22 23:44:49 +00:00
|
|
|
auto &trackFactory = WaveTrackFactory::Get( project );
|
2019-05-06 23:00:10 +00:00
|
|
|
auto &tracks = TrackList::Get( project );
|
2019-05-28 17:12:56 +00:00
|
|
|
auto &window = ProjectWindow::Get( project );
|
2018-10-22 03:14:14 +00:00
|
|
|
|
|
|
|
wxString fileName =
|
|
|
|
FileNames::SelectFile(FileNames::Operation::Open,
|
2019-12-27 03:48:00 +00:00
|
|
|
XO("Select a text file containing labels"),
|
|
|
|
wxEmptyString, // Path
|
|
|
|
wxT(""), // Name
|
|
|
|
wxT("txt"), // Extension
|
|
|
|
{ FileNames::TextFiles, FileNames::AllFiles },
|
|
|
|
wxRESIZE_BORDER, // Flags
|
|
|
|
&window); // Parent
|
2018-10-22 03:14:14 +00:00
|
|
|
|
2019-03-14 17:04:37 +00:00
|
|
|
if (!fileName.empty()) {
|
2018-10-22 03:14:14 +00:00
|
|
|
wxTextFile f;
|
|
|
|
|
|
|
|
f.Open(fileName);
|
|
|
|
if (!f.IsOpened()) {
|
|
|
|
AudacityMessageBox(
|
2019-12-07 19:30:07 +00:00
|
|
|
XO("Could not open file: %s").Format( fileName ) );
|
2018-10-22 03:14:14 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-08-22 23:44:49 +00:00
|
|
|
auto newTrack = std::make_shared<LabelTrack>();
|
2018-10-22 03:14:14 +00:00
|
|
|
wxString sTrackName;
|
|
|
|
wxFileName::SplitPath(fileName, NULL, NULL, &sTrackName, NULL);
|
|
|
|
newTrack->SetName(sTrackName);
|
|
|
|
|
|
|
|
newTrack->Import(f);
|
|
|
|
|
2019-06-21 23:38:38 +00:00
|
|
|
SelectUtilities::SelectNone( project );
|
2018-10-22 03:14:14 +00:00
|
|
|
newTrack->SetSelected(true);
|
2019-05-06 23:00:10 +00:00
|
|
|
tracks.Add( newTrack );
|
2018-10-22 03:14:14 +00:00
|
|
|
|
2019-06-06 13:55:34 +00:00
|
|
|
ProjectHistory::Get( project ).PushState(
|
2019-12-08 17:11:31 +00:00
|
|
|
XO("Imported labels from '%s'").Format( fileName ),
|
|
|
|
XO("Import Labels"));
|
2018-10-22 03:14:14 +00:00
|
|
|
|
2019-05-28 17:12:56 +00:00
|
|
|
window.ZoomAfterImport(nullptr);
|
2018-10-22 03:14:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-25 02:31:11 +00:00
|
|
|
#ifdef USE_MIDI
|
2018-10-22 03:14:14 +00:00
|
|
|
void OnImportMIDI(const CommandContext &context)
|
|
|
|
{
|
|
|
|
auto &project = context.project;
|
2019-05-28 17:12:56 +00:00
|
|
|
auto &window = GetProjectFrame( project );
|
2018-10-22 03:14:14 +00:00
|
|
|
|
|
|
|
wxString fileName = FileNames::SelectFile(FileNames::Operation::Open,
|
2019-12-18 21:32:21 +00:00
|
|
|
XO("Select a MIDI file"),
|
2018-10-22 03:14:14 +00:00
|
|
|
wxEmptyString, // Path
|
|
|
|
wxT(""), // Name
|
|
|
|
wxT(""), // Extension
|
2019-12-27 03:48:00 +00:00
|
|
|
{
|
|
|
|
{ XO("MIDI and Allegro files"),
|
|
|
|
{ wxT("mid"), wxT("midi"), wxT("gro"), }, true },
|
|
|
|
{ XO("MIDI files"),
|
|
|
|
{ wxT("mid"), wxT("midi"), }, true },
|
|
|
|
{ XO("Allegro files"),
|
|
|
|
{ wxT("gro"), }, true },
|
|
|
|
FileNames::AllFiles
|
|
|
|
},
|
2018-10-22 03:14:14 +00:00
|
|
|
wxRESIZE_BORDER, // Flags
|
2019-05-28 17:12:56 +00:00
|
|
|
&window); // Parent
|
2018-10-22 03:14:14 +00:00
|
|
|
|
2019-03-14 17:04:37 +00:00
|
|
|
if (!fileName.empty())
|
2019-06-25 02:18:23 +00:00
|
|
|
DoImportMIDI(project, fileName);
|
2018-10-22 03:14:14 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
void OnImportRaw(const CommandContext &context)
|
|
|
|
{
|
2021-02-13 00:56:41 +00:00
|
|
|
DoImport(context, true);
|
2018-10-22 03:14:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void OnPageSetup(const CommandContext &context)
|
|
|
|
{
|
|
|
|
auto &project = context.project;
|
2019-05-28 17:12:56 +00:00
|
|
|
auto &window = GetProjectFrame( project );
|
|
|
|
HandlePageSetup(&window);
|
2018-10-22 03:14:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void OnPrint(const CommandContext &context)
|
|
|
|
{
|
|
|
|
auto &project = context.project;
|
2019-04-21 21:33:18 +00:00
|
|
|
auto name = project.GetProjectName();
|
2019-05-06 23:00:10 +00:00
|
|
|
auto &tracks = TrackList::Get( project );
|
2019-05-28 17:12:56 +00:00
|
|
|
auto &window = GetProjectFrame( project );
|
|
|
|
HandlePrint(&window, name, &tracks, TrackPanel::Get( project ));
|
2018-10-22 03:14:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void OnExit(const CommandContext &WXUNUSED(context) )
|
|
|
|
{
|
2019-04-26 04:43:17 +00:00
|
|
|
// Simulate the application Exit menu item
|
|
|
|
wxCommandEvent evt{ wxEVT_MENU, wxID_EXIT };
|
|
|
|
wxTheApp->AddPendingEvent( evt );
|
2018-10-22 03:14:14 +00:00
|
|
|
}
|
|
|
|
|
2020-08-10 22:48:59 +00:00
|
|
|
void OnExportFLAC(const CommandContext &context)
|
|
|
|
{
|
|
|
|
DoExport(context.project, "FLAC");
|
|
|
|
}
|
|
|
|
|
2018-10-22 03:14:14 +00:00
|
|
|
}; // struct Handler
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
static CommandHandlerObject &findCommandHandler(AudacityProject &) {
|
|
|
|
// Handler is not stateful. Doesn't need a factory registered with
|
|
|
|
// AudacityProject.
|
|
|
|
static FileActions::Handler instance;
|
|
|
|
return instance;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Menu definitions
|
|
|
|
|
2019-01-06 16:31:52 +00:00
|
|
|
#define FN(X) (& FileActions::Handler :: X)
|
2018-10-22 03:14:14 +00:00
|
|
|
|
2020-02-01 04:44:00 +00:00
|
|
|
namespace {
|
|
|
|
using namespace MenuTable;
|
|
|
|
|
|
|
|
BaseItemSharedPtr FileMenu()
|
2018-10-22 03:14:14 +00:00
|
|
|
{
|
2019-06-09 03:48:42 +00:00
|
|
|
using Options = CommandManager::Options;
|
2018-10-22 03:14:14 +00:00
|
|
|
|
2019-01-09 16:27:32 +00:00
|
|
|
static BaseItemSharedPtr menu{
|
2020-01-29 18:37:02 +00:00
|
|
|
( FinderScope{ findCommandHandler },
|
2020-05-11 15:28:14 +00:00
|
|
|
Menu( wxT("File"), XXO("&File"),
|
2020-01-31 17:06:01 +00:00
|
|
|
Section( "Basic",
|
2020-01-30 16:01:07 +00:00
|
|
|
/*i18n-hint: "New" is an action (verb) to create a NEW project*/
|
|
|
|
Command( wxT("New"), XXO("&New"), FN(OnNew),
|
|
|
|
AudioIONotBusyFlag(), wxT("Ctrl+N") ),
|
|
|
|
|
|
|
|
/*i18n-hint: (verb)*/
|
|
|
|
Command( wxT("Open"), XXO("&Open..."), FN(OnOpen),
|
|
|
|
AudioIONotBusyFlag(), wxT("Ctrl+O") ),
|
|
|
|
|
|
|
|
#ifdef EXPERIMENTAL_RESET
|
|
|
|
// Empty the current project and forget its name and path. DANGEROUS
|
|
|
|
// It's just for developers.
|
|
|
|
// Do not translate this menu item (no XXO).
|
|
|
|
// It MUST not be shown to regular users.
|
|
|
|
Command( wxT("Reset"), XXO("&Dangerous Reset..."), FN(OnProjectReset),
|
|
|
|
AudioIONotBusyFlag() ),
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
Menu( wxT("Recent"),
|
|
|
|
#ifdef __WXMAC__
|
|
|
|
/* i18n-hint: This is the name of the menu item on Mac OS X only */
|
2020-05-11 15:28:14 +00:00
|
|
|
XXO("Open Recent")
|
2020-01-30 16:01:07 +00:00
|
|
|
#else
|
|
|
|
/* i18n-hint: This is the name of the menu item on Windows and Linux */
|
2020-05-11 15:28:14 +00:00
|
|
|
XXO("Recent &Files")
|
2020-01-30 16:01:07 +00:00
|
|
|
#endif
|
|
|
|
,
|
|
|
|
Special( wxT("PopulateRecentFilesStep"),
|
|
|
|
[](AudacityProject &, wxMenu &theMenu){
|
|
|
|
// Recent Files and Recent Projects menus
|
|
|
|
auto &history = FileHistory::Global();
|
|
|
|
history.UseMenu( &theMenu );
|
|
|
|
|
|
|
|
wxWeakRef<wxMenu> recentFilesMenu{ &theMenu };
|
|
|
|
wxTheApp->CallAfter( [=] {
|
|
|
|
// Bug 143 workaround.
|
|
|
|
// The bug is in wxWidgets. For a menu that has scrollers,
|
|
|
|
// the scrollers have an ID of 0 (not wxID_NONE which is -3).
|
|
|
|
// Therefore wxWidgets attempts to find a help string. See
|
|
|
|
// wxFrameBase::ShowMenuHelp(int menuId)
|
|
|
|
// It finds a bogus automatic help string of "Recent &Files"
|
|
|
|
// from that submenu.
|
|
|
|
// So we set the help string for command with Id 0 to empty.
|
|
|
|
if ( recentFilesMenu )
|
|
|
|
recentFilesMenu->GetParent()->SetHelpString( 0, "" );
|
|
|
|
} );
|
|
|
|
} )
|
|
|
|
),
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
Command( wxT("Close"), XXO("&Close"), FN(OnClose),
|
2020-07-26 07:01:37 +00:00
|
|
|
AudioIONotBusyFlag(), wxT("Ctrl+W") )
|
2018-10-22 03:14:14 +00:00
|
|
|
),
|
|
|
|
|
2020-01-31 17:06:01 +00:00
|
|
|
Section( "Save",
|
2020-05-11 15:28:14 +00:00
|
|
|
Menu( wxT("Save"), XXO("&Save Project"),
|
2020-01-30 16:01:07 +00:00
|
|
|
Command( wxT("Save"), XXO("&Save Project"), FN(OnSave),
|
2020-07-03 19:38:57 +00:00
|
|
|
AudioIONotBusyFlag(), wxT("Ctrl+S") ),
|
2020-01-30 16:01:07 +00:00
|
|
|
Command( wxT("SaveAs"), XXO("Save Project &As..."), FN(OnSaveAs),
|
2020-07-03 19:38:57 +00:00
|
|
|
AudioIONotBusyFlag() ),
|
|
|
|
Command( wxT("SaveCopy"), XXO("&Backup Project..."), FN(OnSaveCopy),
|
2020-07-01 05:45:17 +00:00
|
|
|
AudioIONotBusyFlag() )
|
2020-11-27 15:18:05 +00:00
|
|
|
)//,
|
|
|
|
|
|
|
|
// Bug 2600: Compact has interactions with undo/history that are bound
|
|
|
|
// to confuse some users. We don't see a way to recover useful amounts
|
|
|
|
// of space and not confuse users using undo.
|
|
|
|
// As additional space used by aup3 is 50% or so, perfectly valid
|
|
|
|
// approach to this P1 bug is to not provide the 'Compact' menu item.
|
|
|
|
//Command( wxT("Compact"), XXO("Co&mpact Project"), FN(OnCompact),
|
|
|
|
// AudioIONotBusyFlag(), wxT("Shift+A") )
|
2020-01-30 16:01:07 +00:00
|
|
|
),
|
2018-10-22 03:14:14 +00:00
|
|
|
|
2020-01-31 17:06:01 +00:00
|
|
|
Section( "Import-Export",
|
2020-05-11 15:28:14 +00:00
|
|
|
Menu( wxT("Export"), XXO("&Export"),
|
2020-01-30 16:01:07 +00:00
|
|
|
// Enable Export audio commands only when there are audio tracks.
|
|
|
|
Command( wxT("ExportMp3"), XXO("Export as MP&3"), FN(OnExportMp3),
|
|
|
|
AudioIONotBusyFlag() | WaveTracksExistFlag() ),
|
|
|
|
|
|
|
|
Command( wxT("ExportWav"), XXO("Export as &WAV"), FN(OnExportWav),
|
|
|
|
AudioIONotBusyFlag() | WaveTracksExistFlag() ),
|
|
|
|
|
|
|
|
Command( wxT("ExportOgg"), XXO("Export as &OGG"), FN(OnExportOgg),
|
|
|
|
AudioIONotBusyFlag() | WaveTracksExistFlag() ),
|
|
|
|
|
|
|
|
Command( wxT("Export"), XXO("&Export Audio..."), FN(OnExportAudio),
|
|
|
|
AudioIONotBusyFlag() | WaveTracksExistFlag(), wxT("Ctrl+Shift+E") ),
|
|
|
|
|
|
|
|
// Enable Export Selection commands only when there's a selection.
|
|
|
|
Command( wxT("ExportSel"), XXO("Expo&rt Selected Audio..."),
|
|
|
|
FN(OnExportSelection),
|
2021-01-27 22:05:45 +00:00
|
|
|
AudioIONotBusyFlag() | TimeSelectedFlag() | WaveTracksSelectedFlag() ),
|
2020-01-30 16:01:07 +00:00
|
|
|
|
|
|
|
Command( wxT("ExportLabels"), XXO("Export &Labels..."),
|
|
|
|
FN(OnExportLabels),
|
|
|
|
AudioIONotBusyFlag() | LabelTracksExistFlag() ),
|
|
|
|
// Enable Export audio commands only when there are audio tracks.
|
|
|
|
Command( wxT("ExportMultiple"), XXO("Export &Multiple..."),
|
|
|
|
FN(OnExportMultiple),
|
|
|
|
AudioIONotBusyFlag() | WaveTracksExistFlag(), wxT("Ctrl+Shift+L") )
|
|
|
|
#if defined(USE_MIDI)
|
|
|
|
,
|
|
|
|
Command( wxT("ExportMIDI"), XXO("Export MI&DI..."), FN(OnExportMIDI),
|
|
|
|
AudioIONotBusyFlag() | NoteTracksExistFlag() )
|
|
|
|
#endif
|
|
|
|
),
|
|
|
|
|
2020-05-11 15:28:14 +00:00
|
|
|
Menu( wxT("Import"), XXO("&Import"),
|
2020-01-30 16:01:07 +00:00
|
|
|
Command( wxT("ImportAudio"), XXO("&Audio..."), FN(OnImport),
|
|
|
|
AudioIONotBusyFlag(), wxT("Ctrl+Shift+I") ),
|
|
|
|
Command( wxT("ImportLabels"), XXO("&Labels..."), FN(OnImportLabels),
|
|
|
|
AudioIONotBusyFlag() ),
|
|
|
|
#ifdef USE_MIDI
|
|
|
|
Command( wxT("ImportMIDI"), XXO("&MIDI..."), FN(OnImportMIDI),
|
|
|
|
AudioIONotBusyFlag() ),
|
|
|
|
#endif // USE_MIDI
|
|
|
|
Command( wxT("ImportRaw"), XXO("&Raw Data..."), FN(OnImportRaw),
|
|
|
|
AudioIONotBusyFlag() )
|
|
|
|
)
|
|
|
|
),
|
2018-10-22 03:14:14 +00:00
|
|
|
|
2020-01-31 17:06:01 +00:00
|
|
|
Section( "Print",
|
2020-01-30 16:01:07 +00:00
|
|
|
Command( wxT("PageSetup"), XXO("Pa&ge Setup..."), FN(OnPageSetup),
|
|
|
|
AudioIONotBusyFlag() | TracksExistFlag() ),
|
|
|
|
/* i18n-hint: (verb) It's item on a menu. */
|
|
|
|
Command( wxT("Print"), XXO("&Print..."), FN(OnPrint),
|
|
|
|
AudioIONotBusyFlag() | TracksExistFlag() )
|
2018-10-22 03:14:14 +00:00
|
|
|
),
|
|
|
|
|
2020-01-31 17:06:01 +00:00
|
|
|
Section( "Exit",
|
2020-01-30 16:01:07 +00:00
|
|
|
// On the Mac, the Exit item doesn't actually go here...wxMac will
|
|
|
|
// pull it out
|
|
|
|
// and put it in the Audacity menu for us based on its ID.
|
|
|
|
/* i18n-hint: (verb) It's item on a menu. */
|
|
|
|
Command( wxT("Exit"), XXO("E&xit"), FN(OnExit),
|
|
|
|
AlwaysEnabledFlag, wxT("Ctrl+Q") )
|
2020-01-29 21:43:53 +00:00
|
|
|
)
|
2019-01-09 16:27:32 +00:00
|
|
|
) ) };
|
|
|
|
return menu;
|
2018-10-22 03:14:14 +00:00
|
|
|
}
|
|
|
|
|
2020-02-01 04:44:00 +00:00
|
|
|
AttachedItem sAttachment1{
|
|
|
|
wxT(""),
|
|
|
|
Shared( FileMenu() )
|
|
|
|
};
|
2020-08-10 22:48:59 +00:00
|
|
|
|
|
|
|
BaseItemSharedPtr HiddenFileMenu()
|
|
|
|
{
|
|
|
|
static BaseItemSharedPtr menu
|
|
|
|
{
|
|
|
|
(
|
|
|
|
FinderScope{ findCommandHandler },
|
|
|
|
ConditionalItems( wxT("HiddenFileItems"),
|
|
|
|
[]()
|
|
|
|
{
|
|
|
|
// Ensures that these items never appear in a menu, but
|
|
|
|
// are still available to scripting
|
|
|
|
return false;
|
|
|
|
},
|
|
|
|
Menu( wxT("HiddenFileMenu"), XXO("Hidden File Menu"),
|
|
|
|
Command( wxT("ExportFLAC"), XXO("Export as FLAC"),
|
|
|
|
FN(OnExportFLAC),
|
|
|
|
AudioIONotBusyFlag() )
|
|
|
|
)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
};
|
|
|
|
return menu;
|
|
|
|
}
|
|
|
|
|
|
|
|
AttachedItem sAttachment2{
|
|
|
|
wxT(""),
|
|
|
|
Shared( HiddenFileMenu() )
|
|
|
|
};
|
|
|
|
|
2020-02-01 04:44:00 +00:00
|
|
|
}
|
|
|
|
|
2018-10-22 03:14:14 +00:00
|
|
|
#undef FN
|