AUP3: Fix macro path handling
Aside from the breakage I added to it during the AUP3 conversion, there was several other issues discovered in regards to how the export paths were being handled.
This commit is contained in:
parent
5c719e8d65
commit
9d749fef14
|
@ -25,7 +25,6 @@ processing. See also MacrosWindow and ApplyMacroDialog.
|
|||
|
||||
#include "Project.h"
|
||||
#include "ProjectAudioManager.h"
|
||||
#include "ProjectFileIO.h"
|
||||
#include "ProjectHistory.h"
|
||||
#include "ProjectSettings.h"
|
||||
#include "ProjectWindow.h"
|
||||
|
@ -39,7 +38,6 @@ processing. See also MacrosWindow and ApplyMacroDialog.
|
|||
#include "SelectUtilities.h"
|
||||
#include "Shuttle.h"
|
||||
#include "Track.h"
|
||||
#include "export/ExportMP3.h"
|
||||
|
||||
#include "AllThemeResources.h"
|
||||
|
||||
|
@ -47,46 +45,6 @@ processing. See also MacrosWindow and ApplyMacroDialog.
|
|||
|
||||
#include "commands/CommandContext.h"
|
||||
|
||||
// KLUDGE: All commands should be on the same footing
|
||||
// however, for historical reasons we distinguish between
|
||||
// - Effects (which are looked up in effects lists)
|
||||
// - Menu commands (which are held in command manager)
|
||||
// - Specials (which we deal with specially here)
|
||||
enum eCommandType { CtEffect, CtMenu, CtSpecial };
|
||||
|
||||
// TIDY-ME: Not currently translated,
|
||||
// but there are issues to address if we do.
|
||||
// CLEANSPEECH remnant
|
||||
static const std::pair<TranslatableString, CommandID> SpecialCommands[] = {
|
||||
// Use translations of the first members, some other day.
|
||||
// For 2.2.2 we'll get them into the catalog at least.
|
||||
|
||||
{ XO("No Action"), wxT("NoAction") },
|
||||
|
||||
// { wxT("Import"), wxT("Import") }, // non-functioning
|
||||
/* i18n-hint: before is adverb; MP3 names an audio file format */
|
||||
{ XO("Export as MP3 56k before"), wxT("ExportMP3_56k_before") },
|
||||
|
||||
/* i18n-hint: after is adverb; MP3 names an audio file format */
|
||||
{ XO("Export as MP3 56k after"), wxT("ExportMP3_56k_after") },
|
||||
|
||||
/* i18n-hint: FLAC names an audio file format */
|
||||
{ XO("Export as FLAC"), wxT("ExportFLAC") },
|
||||
|
||||
// MP3 OGG and WAV already handled by menu items.
|
||||
#if 0
|
||||
/* i18n-hint: MP3 names an audio file format */
|
||||
{ XO("Export as MP3"), wxT("ExportMP3") },
|
||||
|
||||
/* i18n-hint: Ogg names an audio file format */
|
||||
{ XO("Export as Ogg"), wxT("ExportOgg") },
|
||||
|
||||
/* i18n-hint: WAV names an audio file format */
|
||||
{ XO("Export as WAV"), wxT("ExportWAV") },
|
||||
#endif
|
||||
};
|
||||
// end CLEANSPEECH remnant
|
||||
|
||||
MacroCommands::MacroCommands( AudacityProject &project )
|
||||
: mProject{ project }
|
||||
, mExporter{ project }
|
||||
|
@ -108,16 +66,12 @@ MacroCommands::MacroCommands( AudacityProject &project )
|
|||
|
||||
static const auto MP3Conversion = XO("MP3 Conversion");
|
||||
static const auto FadeEnds = XO("Fade Ends");
|
||||
static const auto SelectToEnds = XO("Select to Ends");
|
||||
|
||||
|
||||
wxArrayStringEx MacroCommands::GetNamesOfDefaultMacros()
|
||||
{
|
||||
return {
|
||||
MP3Conversion.Translation() ,
|
||||
FadeEnds.Translation() ,
|
||||
//Don't add this one anymore, as there is a new menu command for it.
|
||||
//GetCustomTranslation( SelectToEnds ) ,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -135,10 +89,7 @@ void MacroCommands::RestoreMacro(const wxString & name)
|
|||
AddToMacro( wxT("Select"), wxT("Start=\"0\" End=\"1\" RelativeTo=\"ProjectEnd\"") );
|
||||
AddToMacro( wxT("FadeOut") );
|
||||
AddToMacro( wxT("Select"), wxT("Start=\"0\" End=\"0\"") );
|
||||
} else if (name == SelectToEnds.Translation() ){
|
||||
AddToMacro( wxT("SelCursorEnd") );
|
||||
AddToMacro( wxT("SelStartCursor") );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CommandID MacroCommands::GetCommand(int index)
|
||||
|
@ -348,15 +299,7 @@ MacroCommandsCatalog::MacroCommandsCatalog( const AudacityProject *project )
|
|||
if (!project)
|
||||
return;
|
||||
|
||||
// CLEANSPEECH remnant
|
||||
Entries commands;
|
||||
for( const auto &command : SpecialCommands )
|
||||
commands.push_back( {
|
||||
{ command.second, command.first },
|
||||
XO("Special Command")
|
||||
} );
|
||||
|
||||
// end CLEANSPEECH remnant
|
||||
|
||||
PluginManager & pm = PluginManager::Get();
|
||||
EffectManager & em = EffectManager::Get();
|
||||
|
@ -440,8 +383,7 @@ MacroCommandsCatalog::MacroCommandsCatalog( const AudacityProject *project )
|
|||
|
||||
// Sort commands by their user-visible names.
|
||||
// PRL: What exactly should happen if first members of pairs are not unique?
|
||||
// I'm not sure, but at least I can sort stably for a better defined result,
|
||||
// keeping specials before effects and menu items, and lastly commands.
|
||||
// I'm not sure, but at least I can sort stably for a better defined result.
|
||||
auto less =
|
||||
[](const Entry &a, const Entry &b)
|
||||
{ return a.name.StrippedTranslation() <
|
||||
|
@ -486,8 +428,6 @@ auto MacroCommandsCatalog::ByCommandId( const CommandID &commandId ) const
|
|||
{ return entry.name.Internal() == commandId; });
|
||||
}
|
||||
|
||||
|
||||
|
||||
wxString MacroCommands::GetCurrentParamsFor(const CommandID & command)
|
||||
{
|
||||
const PluginID & ID =
|
||||
|
@ -546,238 +486,6 @@ wxString MacroCommands::PromptForPresetFor(const CommandID & command, const wxSt
|
|||
return preset;
|
||||
}
|
||||
|
||||
double MacroCommands::GetEndTime()
|
||||
{
|
||||
AudacityProject *project = &mProject;
|
||||
if( project == NULL )
|
||||
{
|
||||
//AudacityMessageBox( XO("No project to process!") );
|
||||
return -1.0;
|
||||
}
|
||||
auto &tracks = TrackList::Get( *project );
|
||||
|
||||
double endTime = tracks.GetEndTime();
|
||||
return endTime;
|
||||
}
|
||||
|
||||
bool MacroCommands::IsMono( AudacityProject *project )
|
||||
{
|
||||
if( project == NULL )
|
||||
{
|
||||
//AudacityMessageBox( XO("No project and no Audio to process!") );
|
||||
return false;
|
||||
}
|
||||
|
||||
auto &tracks = TrackList::Get( *project );
|
||||
|
||||
return ( tracks.Any() - &Track::IsLeader ).empty();
|
||||
}
|
||||
|
||||
wxString MacroCommands::BuildCleanFileName(const FilePath &fileName,
|
||||
const FileExtension &extension)
|
||||
{
|
||||
const wxFileName newFileName{ fileName };
|
||||
wxString justName = newFileName.GetName();
|
||||
wxString pathName = newFileName.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR);
|
||||
|
||||
// PRL: should this translate?
|
||||
const wxString cleanedString( "macro-output" );
|
||||
|
||||
if (justName.empty()) {
|
||||
wxDateTime now = wxDateTime::Now();
|
||||
int year = now.GetYear();
|
||||
wxDateTime::Month month = now.GetMonth();
|
||||
wxString monthName = now.GetMonthName(month);
|
||||
int dom = now.GetDay();
|
||||
int hour = now.GetHour();
|
||||
int minute = now.GetMinute();
|
||||
int second = now.GetSecond();
|
||||
justName = wxString::Format(wxT("%d-%s-%02d-%02d-%02d-%02d"),
|
||||
year, monthName, dom, hour, minute, second);
|
||||
|
||||
// SetName(cleanedFileName);
|
||||
// bool isStereo;
|
||||
// double endTime = project->mTracks->GetEndTime();
|
||||
// double startTime = 0.0;
|
||||
//OnSelectAll();
|
||||
pathName = FileNames::FindDefaultPath(FileNames::Operation::Export);
|
||||
::AudacityMessageBox(
|
||||
XO("Export recording to %s\n/%s/%s.%s")
|
||||
.Format(pathName, cleanedString, justName, extension),
|
||||
XO("Export recording"),
|
||||
wxOK | wxCENTRE);
|
||||
pathName += wxFileName::GetPathSeparator();
|
||||
}
|
||||
wxString cleanedName = pathName;
|
||||
cleanedName += cleanedString;
|
||||
bool flag = ::wxFileName::FileExists(cleanedName);
|
||||
if (flag == true) {
|
||||
::AudacityMessageBox(
|
||||
XO(
|
||||
"Cannot create directory '%s'. \nFile already exists that is not a directory"),
|
||||
Verbatim( cleanedName ) );
|
||||
return wxString{};
|
||||
}
|
||||
::wxFileName::Mkdir(cleanedName, 0777, wxPATH_MKDIR_FULL); // make sure it exists
|
||||
|
||||
cleanedName += wxFileName::GetPathSeparator();
|
||||
cleanedName += justName;
|
||||
cleanedName += '.';
|
||||
cleanedName += extension;
|
||||
|
||||
return cleanedName;
|
||||
}
|
||||
|
||||
// TODO Move this out of Batch Commands
|
||||
bool MacroCommands::WriteMp3File( const wxString & Name, int bitrate )
|
||||
{ //check if current project is mono or stereo
|
||||
unsigned numChannels = 2;
|
||||
if (IsMono( &mProject )) {
|
||||
numChannels = 1;
|
||||
}
|
||||
|
||||
double endTime = GetEndTime();
|
||||
if( endTime <= 0.0f )
|
||||
return false;
|
||||
if( bitrate <=0 )
|
||||
{
|
||||
// 'No' bitrate given, use the current default.
|
||||
// Use Mp3Stereo to control if export is to a stereo or mono file
|
||||
return mExporter.Process(numChannels, wxT("MP3"), Name, false, 0.0, endTime);
|
||||
}
|
||||
|
||||
|
||||
bool rc;
|
||||
long prevBitRate = gPrefs->Read(wxT("/FileFormats/MP3Bitrate"), 128);
|
||||
gPrefs->Write(wxT("/FileFormats/MP3Bitrate"), bitrate);
|
||||
auto prevMode = MP3RateModeSetting.ReadEnum();
|
||||
MP3RateModeSetting.WriteEnum(MODE_CBR);
|
||||
|
||||
auto cleanup = finally( [&] {
|
||||
gPrefs->Write(wxT("/FileFormats/MP3Bitrate"), prevBitRate);
|
||||
MP3RateModeSetting.WriteEnum(prevMode);
|
||||
gPrefs->Flush();
|
||||
} );
|
||||
|
||||
// Use Mp3Stereo to control if export is to a stereo or mono file
|
||||
rc = mExporter.Process(numChannels, wxT("MP3"), Name, false, 0.0, endTime);
|
||||
return rc;
|
||||
}
|
||||
|
||||
// TIDY-ME: Get rid of special commands and make them part of the
|
||||
// 'menu' system (but not showing on the menu)
|
||||
//
|
||||
// ======= IMPORTANT ========
|
||||
// Special Commands are a KLUDGE whilst we wait for a better system to handle the menu
|
||||
// commands from batch mode.
|
||||
//
|
||||
// Really we should be using a similar (or same) system to that used for effects
|
||||
// so that parameters can be passed to the commands. Many of the menu
|
||||
// commands take a selection as their parameter.
|
||||
//
|
||||
// If you find yourself adding lots of existing commands from the menus here, STOP
|
||||
// and think again.
|
||||
// ======= IMPORTANT ========
|
||||
// CLEANSPEECH remnant
|
||||
bool MacroCommands::ApplySpecialCommand(
|
||||
int WXUNUSED(iCommand), const TranslatableString &friendlyCommand,
|
||||
const CommandID & command, const wxString & params)
|
||||
{
|
||||
if (ReportAndSkip(friendlyCommand, params))
|
||||
return true;
|
||||
|
||||
AudacityProject *project = &mProject;
|
||||
auto &projectFileIO = ProjectFileIO::Get( *project );
|
||||
|
||||
unsigned numChannels = 1; //used to switch between mono and stereo export
|
||||
if (IsMono( &mProject )) {
|
||||
numChannels = 1; //export in mono
|
||||
} else {
|
||||
numChannels = 2; //export in stereo
|
||||
}
|
||||
|
||||
wxString filename;
|
||||
FileExtension extension; // required for correct message
|
||||
if (command == wxT("ExportWAV"))
|
||||
extension = wxT("wav");
|
||||
else if (command == wxT("ExportOgg"))
|
||||
extension = wxT("ogg");
|
||||
else if (command == wxT("ExportFLAC"))
|
||||
extension = wxT("flac");
|
||||
else extension = wxT("mp3");
|
||||
|
||||
if (mFileName.empty()) {
|
||||
filename = BuildCleanFileName(projectFileIO.GetFileName(), extension);
|
||||
}
|
||||
else {
|
||||
filename = BuildCleanFileName(mFileName, extension);
|
||||
}
|
||||
|
||||
const wxString cleanedString("macro-output");
|
||||
// We have a command index, but we don't use it!
|
||||
// TODO: Make this special-batch-command code use the menu item code....
|
||||
// FIXME: TRAP_ERR No error reporting on write file failure in batch mode.
|
||||
if (command == wxT("NoAction")) {
|
||||
return true;
|
||||
} else if (!mFileName.empty() && command == wxT("Import")) {
|
||||
// historically this was in use, now ignored if there
|
||||
return true;
|
||||
} else if (command == wxT("ExportMP3_56k_before")) {
|
||||
#if defined(__WXMSW__)
|
||||
filename.Replace(cleanedString + wxT("\\"), cleanedString + wxT("\\MasterBefore_"), false);
|
||||
#else
|
||||
filename.Replace(cleanedString + wxT("/"), cleanedString + wxT("/MasterBefore_"), false);
|
||||
#endif
|
||||
return WriteMp3File(filename, 56);
|
||||
} else if (command == wxT("ExportMP3_56k_after")) {
|
||||
#if defined(__WXMSW__)
|
||||
filename.Replace(cleanedString + wxT("\\"), cleanedString + wxT("\\MasterAfter_"), false);
|
||||
#else
|
||||
filename.Replace(cleanedString + wxT("/"), cleanedString + wxT("/MasterAfter_"), false);
|
||||
#endif
|
||||
return WriteMp3File(filename, 56);
|
||||
} else if (command == wxT("ExportMP3")) {
|
||||
return WriteMp3File(filename, 0); // 0 bitrate means use default/current
|
||||
} else if (command == wxT("ExportWAV")) {
|
||||
filename.Replace(wxT(".mp3"), wxT(".wav"), false);
|
||||
double endTime = GetEndTime();
|
||||
if (endTime <= 0.0f) {
|
||||
return false;
|
||||
}
|
||||
return mExporter.Process(numChannels, wxT("WAV"), filename, false, 0.0, endTime);
|
||||
} else if (command == wxT("ExportOgg")) {
|
||||
#ifdef USE_LIBVORBIS
|
||||
filename.Replace(wxT(".mp3"), wxT(".ogg"), false);
|
||||
double endTime = GetEndTime();
|
||||
if (endTime <= 0.0f) {
|
||||
return false;
|
||||
}
|
||||
return mExporter.Process(numChannels, wxT("OGG"), filename, false, 0.0, endTime);
|
||||
#else
|
||||
AudacityMessageBox( XO(
|
||||
"Ogg Vorbis support is not included in this build of Audacity"));
|
||||
return false;
|
||||
#endif
|
||||
} else if (command == wxT("ExportFLAC")) {
|
||||
#ifdef USE_LIBFLAC
|
||||
filename.Replace(wxT(".mp3"), wxT(".flac"), false);
|
||||
double endTime = GetEndTime();
|
||||
if (endTime <= 0.0f) {
|
||||
return false;
|
||||
}
|
||||
return mExporter.Process(numChannels, wxT("FLAC"), filename, false, 0.0, endTime);
|
||||
#else
|
||||
AudacityMessageBox(XO(
|
||||
"FLAC support is not included in this build of Audacity"));
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
AudacityMessageBox(
|
||||
XO("Command %s not implemented yet").Format( friendlyCommand ) );
|
||||
return false;
|
||||
}
|
||||
// end CLEANSPEECH remnant
|
||||
|
||||
/// DoAudacityCommand() takes a PluginID and executes the associated command.
|
||||
///
|
||||
/// At the moment flags are used only to indicate whether to prompt for
|
||||
|
@ -909,15 +617,6 @@ bool MacroCommands::ApplyCommand( const TranslatableString &friendlyCommand,
|
|||
const CommandID & command, const wxString & params,
|
||||
CommandContext const * pContext)
|
||||
{
|
||||
|
||||
// Test for a special command.
|
||||
// CLEANSPEECH remnant
|
||||
for( size_t i = 0; i < WXSIZEOF( SpecialCommands ); ++i ) {
|
||||
if( command == SpecialCommands[i].second )
|
||||
return ApplySpecialCommand( i, friendlyCommand, command, params );
|
||||
}
|
||||
// end CLEANSPEECH remnant
|
||||
|
||||
// Test for an effect.
|
||||
const PluginID & ID =
|
||||
EffectManager::Get().GetEffectByIdentifier( command );
|
||||
|
|
|
@ -72,9 +72,6 @@ class MacroCommands final {
|
|||
bool ApplyCommandInBatchMode( const TranslatableString &friendlyCommand,
|
||||
const CommandID & command, const wxString ¶ms,
|
||||
CommandContext const * pContext = NULL);
|
||||
bool ApplySpecialCommand(
|
||||
int iCommand, const TranslatableString &friendlyCommand,
|
||||
const CommandID & command, const wxString & params);
|
||||
bool ApplyEffectCommand(
|
||||
const PluginID & ID, const TranslatableString &friendlyCommand,
|
||||
const CommandID & command,
|
||||
|
@ -82,13 +79,6 @@ class MacroCommands final {
|
|||
bool ReportAndSkip( const TranslatableString & friendlyCommand, const wxString & params );
|
||||
void AbortBatch();
|
||||
|
||||
// Utility functions for the special commands.
|
||||
static wxString BuildCleanFileName(const FilePath &fileName,
|
||||
const FileExtension &extension);
|
||||
bool WriteMp3File( const wxString & Name, int bitrate );
|
||||
double GetEndTime();
|
||||
static bool IsMono( AudacityProject *project );
|
||||
|
||||
// These commands do not depend on the command list.
|
||||
static void MigrateLegacyChains();
|
||||
static wxArrayString GetNames();
|
||||
|
|
|
@ -148,6 +148,19 @@ void AudacityProject::SetProjectName(const wxString &name)
|
|||
mName = name;
|
||||
}
|
||||
|
||||
FilePath AudacityProject::GetInitialImportPath() const
|
||||
{
|
||||
return mInitialImportPath;
|
||||
}
|
||||
|
||||
void AudacityProject::SetInitialImportPath(const FilePath &path)
|
||||
{
|
||||
if (mInitialImportPath.empty())
|
||||
{
|
||||
mInitialImportPath = path;
|
||||
}
|
||||
}
|
||||
|
||||
AUDACITY_DLL_API wxFrame &GetProjectFrame( AudacityProject &project )
|
||||
{
|
||||
auto ptr = project.GetFrame();
|
||||
|
|
|
@ -138,7 +138,12 @@ class AUDACITY_DLL_API AudacityProject final
|
|||
const wxString &GetProjectName() const;
|
||||
void SetProjectName(const wxString &name);
|
||||
|
||||
private:
|
||||
// Used exclusively in batch mode, this allows commands to remember
|
||||
// and use the initial import path
|
||||
FilePath GetInitialImportPath() const;
|
||||
void SetInitialImportPath(const FilePath &path);
|
||||
|
||||
private:
|
||||
|
||||
// The project's name
|
||||
wxString mName;
|
||||
|
@ -146,6 +151,8 @@ class AUDACITY_DLL_API AudacityProject final
|
|||
static int mProjectCounter;// global counter.
|
||||
int mProjectNo; // count when this project was created.
|
||||
|
||||
FilePath mInitialImportPath;
|
||||
|
||||
public:
|
||||
bool mbBusyImporting{ false }; // used to fix bug 584
|
||||
int mBatchMode{ 0 };// 0 means not, >0 means in batch mode.
|
||||
|
|
|
@ -1116,6 +1116,7 @@ ProjectFileManager::AddImportedTracks(const FilePath &fileName,
|
|||
// the filename to the just imported path.
|
||||
if (initiallyEmpty && projectFileIO.IsTemporary()) {
|
||||
project.SetProjectName(fn.GetName());
|
||||
project.SetInitialImportPath(fn.GetPath());
|
||||
projectFileIO.SetProjectTitle();
|
||||
}
|
||||
|
||||
|
@ -1127,7 +1128,9 @@ ProjectFileManager::AddImportedTracks(const FilePath &fileName,
|
|||
|
||||
// If pNewTrackList is passed in non-NULL, it gets filled with the pointers to NEW tracks.
|
||||
bool ProjectFileManager::Import(
|
||||
const FilePath &fileName, WaveTrackArray* pTrackArray /*= NULL*/)
|
||||
const FilePath &fileName,
|
||||
WaveTrackArray *pTrackArray /* = nullptr */,
|
||||
bool addToHistory /* = true */)
|
||||
{
|
||||
auto &project = mProject;
|
||||
auto &projectFileIO = ProjectFileIO::Get(project);
|
||||
|
@ -1145,13 +1148,17 @@ bool ProjectFileManager::Import(
|
|||
// If the project was clean and temporary (not permanently saved), then set
|
||||
// the filename to the just imported path.
|
||||
if (initiallyEmpty && projectFileIO.IsTemporary()) {
|
||||
project.SetProjectName(wxFileName(fileName).GetName());
|
||||
wxFileName fn(fileName);
|
||||
project.SetProjectName(fn.GetName());
|
||||
project.SetInitialImportPath(fn.GetPath());
|
||||
projectFileIO.SetProjectTitle();
|
||||
}
|
||||
|
||||
history.PushState(XO("Imported '%s'").Format(fileName), XO("Import"));
|
||||
|
||||
FileHistory::Global().Append(fileName);
|
||||
if (addToHistory) {
|
||||
FileHistory::Global().Append(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -1182,7 +1189,9 @@ bool ProjectFileManager::Import(
|
|||
if (!success)
|
||||
return false;
|
||||
|
||||
FileHistory::Global().Append(fileName);
|
||||
if (addToHistory) {
|
||||
FileHistory::Global().Append(fileName);
|
||||
}
|
||||
|
||||
// no more errors, commit
|
||||
committed = true;
|
||||
|
@ -1204,7 +1213,9 @@ bool ProjectFileManager::Import(
|
|||
// If the project was clean and temporary (not permanently saved), then set
|
||||
// the filename to the just imported path.
|
||||
if (initiallyEmpty && projectFileIO.IsTemporary()) {
|
||||
project.SetProjectName(wxFileName(fileName).GetName());
|
||||
wxFileName fn(fileName);
|
||||
project.SetProjectName(fn.GetName());
|
||||
project.SetInitialImportPath(fn.GetPath());
|
||||
projectFileIO.SetProjectTitle();
|
||||
}
|
||||
|
||||
|
|
|
@ -92,7 +92,9 @@ public:
|
|||
void OpenFile(const FilePath &fileName, bool addtohistory = true);
|
||||
|
||||
// If pNewTrackList is passed in non-NULL, it gets filled with the pointers to NEW tracks.
|
||||
bool Import(const FilePath &fileName, WaveTrackArray *pTrackArray = NULL);
|
||||
bool Import(const FilePath &fileName,
|
||||
WaveTrackArray *pTrackArray = nullptr,
|
||||
bool addToHistory = true);
|
||||
|
||||
// Takes array of unique pointers; returns array of shared
|
||||
std::vector< std::shared_ptr<Track> >
|
||||
|
|
|
@ -48,7 +48,7 @@ void ImportCommand::PopulateOrExchange(ShuttleGui & S)
|
|||
}
|
||||
|
||||
bool ImportCommand::Apply(const CommandContext & context){
|
||||
return ProjectFileManager::Get( context.project ).Import(mFileName);
|
||||
return ProjectFileManager::Get( context.project ).Import(mFileName, nullptr, false);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -466,6 +466,14 @@ bool Exporter::Process(bool selectedOnly, double t0, double t1)
|
|||
// Get rid of mixerspec
|
||||
mMixerSpec.reset();
|
||||
|
||||
if (success) {
|
||||
if (mFormatName.empty()) {
|
||||
gPrefs->Write(wxT("/Export/Format"), mPlugins[mFormat]->GetFormat(mSubFormat));
|
||||
}
|
||||
|
||||
FileNames::UpdateDefaultPath(FileNames::Operation::Export, mFilename.GetPath());
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
@ -774,11 +782,6 @@ bool Exporter::GetFilename()
|
|||
//
|
||||
bool Exporter::CheckFilename()
|
||||
{
|
||||
if( mFormatName.empty() )
|
||||
gPrefs->Write(wxT("/Export/Format"), mPlugins[mFormat]->GetFormat(mSubFormat));
|
||||
|
||||
FileNames::UpdateDefaultPath(FileNames::Operation::Export, mFilename.GetPath());
|
||||
|
||||
//
|
||||
// To be even safer, return a temporary file name based
|
||||
// on this one...
|
||||
|
@ -924,6 +927,8 @@ bool Exporter::ExportTracks()
|
|||
::wxRemoveFile(mActualName.GetFullPath());
|
||||
::wxRenameFile(mFilename.GetFullPath(), mActualName.GetFullPath());
|
||||
}
|
||||
// Restore filname
|
||||
mFilename = mActualName;
|
||||
}
|
||||
else {
|
||||
if ( ! success )
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "../WaveTrack.h"
|
||||
#include "../commands/CommandContext.h"
|
||||
#include "../commands/CommandManager.h"
|
||||
#include "../export/ExportMP3.h"
|
||||
#include "../export/ExportMultiple.h"
|
||||
#include "../import/Import.h"
|
||||
#include "../import/ImportMIDI.h"
|
||||
|
@ -40,7 +41,10 @@
|
|||
|
||||
// private helper classes and functions
|
||||
namespace {
|
||||
void DoExport( AudacityProject &project, const FileExtension & Format )
|
||||
|
||||
void DoExport(AudacityProject &project,
|
||||
const FileExtension &format,
|
||||
const wxString &prefix = {})
|
||||
{
|
||||
auto &tracks = TrackList::Get( project );
|
||||
auto &projectFileIO = ProjectFileIO::Get( project );
|
||||
|
@ -49,65 +53,83 @@ void DoExport( AudacityProject &project, const FileExtension & Format )
|
|||
|
||||
double t0 = 0.0;
|
||||
double t1 = tracks.GetEndTime();
|
||||
wxString projectName = project.GetProjectName();
|
||||
|
||||
// Prompt for file name and/or extension?
|
||||
bool bPromptingRequired =
|
||||
(project.mBatchMode == 0) || projectFileIO.GetFileName().empty() ||
|
||||
Format.empty();
|
||||
wxString filename;
|
||||
bool bPromptingRequired = !project.mBatchMode ||
|
||||
projectName.empty() ||
|
||||
format.empty();
|
||||
|
||||
if (!bPromptingRequired) {
|
||||
|
||||
// We're in batch mode, and we have an mFileName and Format.
|
||||
wxString extension = Format;
|
||||
extension.MakeLower();
|
||||
|
||||
filename =
|
||||
MacroCommands::BuildCleanFileName(projectFileIO.GetFileName(), extension);
|
||||
|
||||
// Bug 1854, No warning of file overwrite
|
||||
// (when export is called from Macros).
|
||||
int counter = 0;
|
||||
bPromptingRequired = wxFileExists(filename);
|
||||
|
||||
// We'll try alternative names to avoid overwriting.
|
||||
while ( bPromptingRequired && counter < 100 ) {
|
||||
counter++;
|
||||
wxString number;
|
||||
number.Printf("%03i", counter);
|
||||
// So now the name has a number in it too.
|
||||
filename = MacroCommands::BuildCleanFileName(
|
||||
projectFileIO.GetFileName() + number, extension);
|
||||
bPromptingRequired = wxFileExists(filename);
|
||||
}
|
||||
// If we've run out of alternative names, we will fall back to prompting
|
||||
// - even if in a macro.
|
||||
}
|
||||
|
||||
|
||||
if (bPromptingRequired)
|
||||
{
|
||||
bool success = false;
|
||||
if (bPromptingRequired) {
|
||||
// Do export with prompting.
|
||||
e.SetDefaultFormat(Format);
|
||||
e.Process(false, t0, t1);
|
||||
e.SetDefaultFormat(format);
|
||||
success = e.Process(false, t0, t1);
|
||||
}
|
||||
else
|
||||
{
|
||||
FileHistory::Global().Append(filename);
|
||||
else {
|
||||
// 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();
|
||||
wxFileName fileName(pathName,
|
||||
prefix + projectName,
|
||||
format.Lower());
|
||||
|
||||
// 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;
|
||||
|
||||
// We're in batch mode, the file does not exist already.
|
||||
// We really can proceed without prompting.
|
||||
int nChannels = MacroCommands::IsMono( &project ) ? 1 : 2;
|
||||
e.Process(
|
||||
success = e.Process(
|
||||
nChannels, // numChannels,
|
||||
Format, // type,
|
||||
filename, // filename,
|
||||
format, // type,
|
||||
fullPath, // full path,
|
||||
false, // selectedOnly,
|
||||
t0, // t0
|
||||
t1 // t1
|
||||
);
|
||||
}
|
||||
|
||||
if (success && !project.mBatchMode) {
|
||||
FileHistory::Global().Append(e.GetAutoExportFileName().GetFullPath());
|
||||
}
|
||||
}
|
||||
|
||||
void WriteMp3File(AudacityProject &project, const wxString &prefix)
|
||||
{
|
||||
long prevBitRate = gPrefs->Read(wxT("/FileFormats/MP3Bitrate"), 128);
|
||||
gPrefs->Write(wxT("/FileFormats/MP3Bitrate"), 56);
|
||||
auto prevMode = MP3RateModeSetting.ReadEnum();
|
||||
MP3RateModeSetting.WriteEnum(MODE_CBR);
|
||||
|
||||
DoExport(project, wxT("MP3"), prefix);
|
||||
|
||||
gPrefs->Write(wxT("/FileFormats/MP3Bitrate"), prevBitRate);
|
||||
MP3RateModeSetting.WriteEnum(prevMode);
|
||||
gPrefs->Flush();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Compact dialog
|
||||
|
@ -629,6 +651,21 @@ void OnExit(const CommandContext &WXUNUSED(context) )
|
|||
wxTheApp->AddPendingEvent( evt );
|
||||
}
|
||||
|
||||
void OnExportMP3_56k_before(const CommandContext &context)
|
||||
{
|
||||
WriteMp3File(context.project, wxT("MasterBefore_"));
|
||||
}
|
||||
|
||||
void OnExportMP3_56k_after(const CommandContext &context)
|
||||
{
|
||||
WriteMp3File(context.project, wxT("MasterAfter_"));
|
||||
}
|
||||
|
||||
void OnExportFLAC(const CommandContext &context)
|
||||
{
|
||||
DoExport(context.project, "FLAC");
|
||||
}
|
||||
|
||||
}; // struct Handler
|
||||
|
||||
} // namespace
|
||||
|
@ -798,6 +835,42 @@ AttachedItem sAttachment1{
|
|||
wxT(""),
|
||||
Shared( FileMenu() )
|
||||
};
|
||||
|
||||
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("ExportMP3_56k_before"), XXO("Export as MP3 56k before"),
|
||||
FN(OnExportMP3_56k_before),
|
||||
AudioIONotBusyFlag() ),
|
||||
Command( wxT("ExportMP3_56k_after"), XXO("Export as MP3 56k after"),
|
||||
FN(OnExportMP3_56k_after),
|
||||
AudioIONotBusyFlag() ),
|
||||
Command( wxT("ExportFLAC"), XXO("Export as FLAC"),
|
||||
FN(OnExportFLAC),
|
||||
AudioIONotBusyFlag() )
|
||||
)
|
||||
)
|
||||
)
|
||||
};
|
||||
return menu;
|
||||
}
|
||||
|
||||
AttachedItem sAttachment2{
|
||||
wxT(""),
|
||||
Shared( HiddenFileMenu() )
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#undef FN
|
||||
|
|
Loading…
Reference in New Issue