28#include <wx/checkbox.h>
29#include <wx/textctrl.h>
31#include <wx/radiobut.h>
32#include <wx/stattext.h>
45#if wxUSE_ACCESSIBILITY
54 {
"project",
XO(
"Entire &Project") },
55 {
"split",
XO(
"M&ultiple Files") },
56 {
"selection",
XO(
"Curren&t selection") }
64 {
"tracks",
XO(
"Tracks") },
65 {
"labels",
XO(
"Labels") }
72 {
"name",
XO(
"Using Label/Track Name") },
73 {
"num_and_name",
XO(
"Numbering before Label/Track Name") },
74 {
"num_and_prefix",
XO(
"Numbering after File name prefix") }
143 const wxString& defaultName,
144 const wxString& defaultFormat)
151 PopulateOrExchange(
S);
153 SetMinSize({GetBestSize().GetWidth(), -1});
157 if(exportPath.empty())
159 filename.SetPath(exportPath);
162 filename.SetEmptyExt();
163 if(defaultName.empty())
165 filename.SetName(
_(
"untitled"));
167 filename.SetName(defaultName);
177 wxString
format = defaultFormat;
185 const auto hasLabels = !labelTracks.empty() &&
186 (*labelTracks.begin())->GetNumLabels() > 0;
193 mRangeSelection->Disable();
195 mRangeProject->SetValue(
true);
197 else if (!hasLabels && !hasMultipleWaveTracks)
198 mRangeSelection->MoveAfterInTabOrder(mRangeProject);
202 mSplitByLabels->Disable();
203 if (hasMultipleWaveTracks)
204 mSplitByTracks->SetValue(
true);
207 if (!hasMultipleWaveTracks)
209 mSplitByTracks->Disable();
211 mSplitByLabels->SetValue(
true);
214 if (!hasLabels && !hasMultipleWaveTracks)
216 mRangeSplit->Disable();
218 mRangeProject->SetValue(
true);
219 mSplitsPanel->Hide();
223 mSplitsPanel->Hide();
225 mExportOptionsPanel->SetCustomMappingEnabled(!mRangeSplit->GetValue());
227 mIncludeAudioBeforeFirstLabel->Enable(mSplitByLabels->GetValue());
230 mSplitFileNamePrefix->Disable();
243#if defined(__WXMSW__)
254 S.StartVerticalLay();
267 S.StartHorizontalLay(wxSHRINK | wxALIGN_TOP);
269 if(
auto prompt =
S.AddPrompt(
XO(
"Export Range:")))
270 prompt->SetMinSize({145, -1});
272 S.EndHorizontalLay();
274 S.StartVerticalLay();
279 .Name(
XO(
"Export entire project"))
282 .Name(
XO(
"Export multiple files"))
285 .Name(
XO(
"Export current selection"))
287#if wxUSE_ACCESSIBILITY
293 S.EndRadioButtonGroup();
315 S.StartMultiColumn(2);
317 S.StartStatic(
XO(
"Split files based on:"));
319 S.StartVerticalLay();
326 S.EndRadioButtonGroup();
328 S.StartHorizontalLay(wxALIGN_TOP);
335 S.EndHorizontalLay();
341 S.StartStatic(
XO(
"Name files:"));
343 S.StartVerticalLay();
351 S.EndRadioButtonGroup();
352 S.StartHorizontalLay(wxALIGN_TOP);
357 .AddTextBox(
XO(
"File name prefix:"), {}, 0);
359 S.EndHorizontalLay();
378 S.StartHorizontalLay(wxEXPAND);
381 S.AddSpace(1, 1, wxEXPAND);
382 S.Id(wxID_CANCEL).AddButton(
XO(
"&Cancel"), wxBOTTOM);
383 S.Id(wxID_OK).AddButton(
XO(
"&Export"), wxRIGHT | wxBOTTOM,
true);
385 S.EndHorizontalLay();
437 std::vector<Tags*> tags;
438 std::vector<wxString>
names;
443 tags.push_back(&spec.tags);
444 names.push_back(spec.filename.GetFullName());
452 XO(
"Edit Metadata Tags"),
XO(
"Exported Tags"));
464 if(selectedPlugin ==
nullptr)
471 if(!wxDirExists(path))
474 if(!wxDirExists(path))
497 ?
XO(
"Successfully exported the following %lld file(s).")
499 ?
XO(
"Something went wrong after exporting the following %lld file(s).")
501 ?
XO(
"Export canceled after exporting the following %lld file(s).")
503 ?
XO(
"Export stopped after exporting the following %lld file(s).")
504 :
XO(
"Something went really wrong after exporting the following %lld file(s).")
505 ).
Format((
long long) exportedFiles.size());
508 for (
auto& path : exportedFiles)
509 fileList += path +
'\n';
524 if (filename.FileExists()) {
526 XO(
"A file named \"%s\" already exists. Replace?")
527 .
Format( filename.GetFullPath() ),
529 wxYES_NO | wxICON_EXCLAMATION);
530 if (result != wxYES) {
537 .
SetPlugin(selectedPlugin, selectedFormat)
545 auto t0 = selectedOnly
546 ? std::max(.0, viewInfo.selectedRegion.t0())
549 auto t1 = selectedOnly
554 if(exportedTracks.empty())
557 selectedOnly ?
XO(
"All selected audio is muted.") :
XO(
"All audio is muted."),
566 builder.
SetRange(t0, t1, selectedOnly);
568 std::unique_ptr<MixerOptions::Downmix> tempMixerSpec;
577 std::vector<bool> channelMask(
578 tracks.sum([](
const auto track) { return track->NChannels(); }),
580 unsigned trackIndex = 0;
581 for(
const auto track :
tracks)
585 channelMask.assign(channelMask.size(),
false);
586 for(
unsigned i = 0; i < track->NChannels(); ++i)
587 channelMask[trackIndex++] =
true;
590 if(!track->GetMute() && (!selectedOnly || track->GetSelected()))
592 for(
unsigned i = 0; i < track->NChannels(); ++i)
593 channelMask[trackIndex++] =
true;
596 trackIndex += track->NChannels();
629 auto enableMeta =
false;
642 if(selectedPlugin ==
nullptr)
672 return std::all_of(range.begin(), range.end(),
673 [](
auto *pTrack){ return IsMono(*pTrack); }
686 const auto numLabels = labels->GetNumLabels();
688 auto numFiles = numLabels;
690 std::vector<ExportSetting> exportSettings;
691 exportSettings.reserve(numFiles);
714 while( fileIndex < numLabels ) {
717 if( fileIndex < 0 ) {
722 info = labels->GetLabel(fileIndex);
730 }
else if( fileIndex < numLabels - 1 ) {
732 const LabelStruct *info1 = labels->GetLabel(fileIndex+1);
739 name =
_(
"untitled");
746 name.Printf(
wxT(
"%s-%02d"), prefix, fileIndex + 1);
747 }
else if( addNumber ) {
750 name.Prepend(wxString::Format(
wxT(
"%02d-"), fileIndex + 1));
765 if (exportSettings.empty())
771 setting.
tags = exportSettings.back().tags;
778 exportSettings.push_back(setting);
786 const wxString& prefix)
795 const auto numWaveTracks = waveTracks.size();
800 std::vector<ExportSetting> exportSettings;
802 exportSettings.reserve(numWaveTracks);
813 for (
auto tr : waveTracks) {
816 setting.
t0 = skipSilenceAtBeginning ? tr->GetStartTime() : 0;
817 setting.
t1 = tr->GetEndTime();
823 title = tr->GetName();
831 wxString::Format(
wxT(
"%02d-"), fileIndex+1));
835 name = (wxString::Format(
wxT(
"%s-%02d"), prefix, fileIndex+1));
852 if(exportSettings.empty())
858 setting.
tags = exportSettings.back().tags;
864 exportSettings.push_back(setting);
883 if( activeSetting.filename.GetName().empty() )
887 ok =
DoExport(plugin, formatIndex, parameters, activeSetting.filename, activeSetting.channels,
888 activeSetting.t0, activeSetting.t1,
false, activeSetting.tags, exporterFiles);
893 XO(
"Continue to export remaining files?"),
895 wxYES_NO | wxNO_DEFAULT | wxICON_WARNING);
896 if (dlgMessage.ShowModal() != wxID_YES ) {
927 tr->SetSelected(
false);
932 for (
auto tr : waveTracks) {
934 wxLogDebug(
"Get setting %i", count );
937 if( activeSetting.filename.GetName().empty() ){
944 tr->SetSelected(
true);
947 ok =
DoExport(plugin, formatIndex, parameters, activeSetting.filename, activeSetting.channels,
948 activeSetting.t0, activeSetting.t1,
true, activeSetting.tags, exporterFiles);
953 XO(
"Continue to export remaining files?"),
955 wxYES_NO | wxNO_DEFAULT | wxICON_WARNING);
956 if (dlgMessage.ShowModal() != wxID_YES ) {
976 const wxFileName& filename,
978 double t0,
double t1,
bool selectedOnly,
984 wxLogDebug(
wxT(
"Doing multiple Export: File name \"%s\""), (filename.GetFullName()));
985 wxLogDebug(
wxT(
"Channels: %i, Start: %lf, End: %lf "), channels, t0, t1);
987 wxLogDebug(
wxT(
"Selected Region Only"));
989 wxLogDebug(
wxT(
"Whole Project"));
998 backup.SetName(
name.GetName() +
999 wxString::Format(
wxT(
"%d"), suffix));
1002 while (backup.FileExists());
1003 ::wxRenameFile(filename.GetFullPath(), backup.GetFullPath());
1008 wxString base(
name.GetName());
1009 while (
name.FileExists()) {
1010 name.SetName(wxString::Format(
wxT(
"%s-%d"), base, i++));
1014 bool success{
false};
1015 const wxString fullPath{
name.GetFullPath()};
1017 auto cleanup =
finally( [&] {
1018 if (backup.IsOk()) {
1021 ::wxRemoveFile(backup.GetFullPath());
1024 ::wxRemoveFile(fullPath);
1025 ::wxRenameFile(backup.GetFullPath(), fullPath);
1031 ::wxRemoveFile(fullPath);
1039 .SetParameters(parameters)
1040 .SetRange(t0, t1, selectedOnly)
1042 .SetNumChannels(channels)
1043 .SetFileName(fullPath)
1044 .SetSampleRate(mExportOptionsPanel->GetSampleRate())
1051 exportedFiles.push_back(fullPath);
int AudacityMessageBox(const TranslatableString &message, const TranslatableString &caption, long style, wxWindow *parent, int x, int y)
EVT_BUTTON(wxID_NO, DependencyDialog::OnNo) EVT_BUTTON(wxID_YES
const TranslatableString name
void ShowExportErrorDialog(const TranslatableString &message, const TranslatableString &caption, bool allowReporting)
EVT_COMMAND(wxID_ANY, EVT_FREQUENCYTEXTCTRL_UPDATED, LabelDialog::OnFreqUpdate) LabelDialog
Wrap wxMessageDialog so that caption IS translatable.
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
This specialization of Setting for bool adds a Toggle method to negate the saved value.
double GetStartTime() const
Get the minimum of Start() values of intervals, or 0 when none.
ExportResult DoExportSplitByTracks(const ExportPlugin &plugin, int formatIndex, const ExportProcessor::Parameters ¶meters, FilePaths &exporterFiles)
void OnEditMetadata(wxCommandEvent &event)
void OnIncludeAudioBeforeFirstLabelChange(wxCommandEvent &)
wxRadioButton * mRangeSplit
wxCheckBox * mSkipSilenceAtBeginning
bool mExportSettingsDirty
wxCheckBox * mOverwriteExisting
void UpdateLabelExportSettings(const ExportPlugin &plugin, int formatIndex, bool byName, bool addNumber, const wxString &prefix)
void OnHelp(wxCommandEvent &event)
wxRadioButton * mRangeSelection
void OnExport(wxCommandEvent &event)
void OnTrimBlankSpaceBeforeFirstClip(wxCommandEvent &)
void PopulateOrExchange(ShuttleGui &S)
ExportResult DoExport(const ExportPlugin &plugin, int formatIndex, const ExportProcessor::Parameters ¶meters, const wxFileName &filename, int channels, double t0, double t1, bool selectedOnly, const Tags &tags, FilePaths &exportedFiles)
void OnSplitNamePolicyChange(wxCommandEvent &event)
void OnExportRangeChange(wxCommandEvent &event)
void OnFileNamePrefixChange(wxCommandEvent &)
wxRadioButton * mSplitUseName
bool Show(bool show=true) override
ExportResult DoExportSplitByLabels(const ExportPlugin &plugin, int formatIndex, const ExportProcessor::Parameters ¶meters, FilePaths &exporterFiles)
void UpdateExportSettings()
wxRadioButton * mSplitUseNumAndName
wxRadioButton * mSplitByTracks
ExportFilePanel * mExportOptionsPanel
~ExportAudioDialog() override
wxRadioButton * mSplitByLabels
void UpdateTrackExportSettings(const ExportPlugin &plugin, int formatIndex, bool byName, bool addNumber, const wxString &prefix)
wxTextCtrl * mSplitFileNamePrefix
void OnFormatChange(wxCommandEvent &event)
AudacityProject & mProject
void OnSplitModeChange(wxCommandEvent &event)
wxCheckBox * mIncludeAudioBeforeFirstLabel
std::vector< ExportSetting > mExportSettings
wxRadioButton * mRangeProject
wxRadioButton * mSplitUseNumAndPrefix
const ExportPlugin * GetPlugin() const
int GetSampleRate() const
void SetCustomMappingEnabled(bool enabled)
MixerOptions::Downmix * GetMixerSpec() const
ExportProcessor::Parameters GetParameters() const
Main class to control the export function.
virtual FormatInfo GetFormatInfo(int index) const =0
Returns FormatInfo structure for given index if it's valid, or a default one. FormatInfo::format isn'...
std::vector< std::tuple< ExportOptionID, ExportValue > > Parameters
ExportTaskBuilder & SetPlugin(const ExportPlugin *plugin, int format=0) noexcept
ExportTaskBuilder & SetMixerSpec(MixerOptions::Downmix *mixerSpec) noexcept
ExportTask Build(AudacityProject &project)
ExportTaskBuilder & SetParameters(ExportProcessor::Parameters parameters) noexcept
ExportTaskBuilder & SetNumChannels(unsigned numChannels) noexcept
ExportTaskBuilder & SetSampleRate(double sampleRate) noexcept
ExportTaskBuilder & SetFileName(const wxFileName &filename)
ExportTaskBuilder & SetRange(double t0, double t1, bool selectedOnly=false) noexcept
static TrackIterRange< const WaveTrack > FindExportWaveTracks(const TrackList &tracks, bool selectedOnly)
static void ShowHelp(wxWindow *parent, const FilePath &localFileName, const URLString &remoteURL, bool bModal=false, bool alwaysDefaultBrowser=false)
static void ShowInfoDialog(wxWindow *parent, const TranslatableString &dlogTitle, const TranslatableString &shortMsg, const wxString &message, const int xSize, const int ySize)
Displays cuttable information in a text ctrl, with an OK button.
static ImportExport & Get(AudacityProject &project)
void SetPreferredExportRate(double rate)
double GetPreferredExportRate() const
static constexpr double InvalidRate
static bool SanitiseFilename(wxString &name, const wxString &sub)
Check a proposed file name string for illegal characters and remove them return true iff name is "vis...
A LabelStruct holds information for ONE label in a LabelTrack.
SelectedRegion selectedRegion
A LabelTrack is a Track that holds labels (LabelStruct).
static SelectionState & Get(AudacityProject &project)
bool Write(const T &value)
Write value to config and return true if successful.
bool Read(T *pVar) const
overload of Read returning a boolean that is true if the value was previously defined */
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
Specialization of Setting for strings.
A flat linked list of tracks supporting Add, Remove, Clear, and Contains, serialization of the list o...
double GetEndTime() const
Return the greatest end time of the tracks, or 0 when no tracks.
auto Any() -> TrackIterRange< TrackType >
static TrackList & Get(AudacityProject &project)
NotifyingSelectedRegion selectedRegion
static ViewInfo & Get(AudacityProject &project)
A Track that contains audio waveform data.
bool GetMute() const override
May vary asynchronously.
bool GetSolo() const override
May vary asynchronously.
An alternative to using wxWindowAccessible, which in wxWidgets 3.1.1 contained GetParent() which was ...
Extend wxArrayString with move operations and construction and insertion fromstd::initializer_list.
bool IsMono(const Channel &channel)
Whether the channel is mono.
ExportResult Show(ExportTask exportTask)
void ExceptionWrappedCall(Callable callable)
FILES_API void MakeNameUnique(FilePaths &otherNames, wxFileName &newName)
FILES_API FilePath FindDefaultPath(Operation op)
auto begin(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
constexpr auto sampleRate
ChoiceSetting ExportAudioSplitMode
unsigned GetNumExportChannels(const TrackList &tracks)
BoolSetting ExportAudioOverwriteExisting
BoolSetting ExportAudioIncludeAudioBeforeFirstLabel
StringSetting ExportAudioDefaultFormat
BoolSetting ExportAudioSkipSilenceAtBeginning
ChoiceSetting ExportAudioSplitNamePolicy
@ TrimBlankSpaceBeforeFirstClipID
@ OverwriteExistingFilesID
@ IncludeAudioBeforeFirstLabelID
@ ExportSplitNamePolicyTrackNameID
@ ExportSplitNamePolicyNumberingBeforeNameID
@ ExportSplitNamePolicyNumberingAfterPrefixID
StringSetting ExportAudioDefaultPath
ChoiceSetting ExportAudioExportRange
void swap(std::unique_ptr< Alg_seq > &a, std::unique_ptr< Alg_seq > &b)
A private class used to store the information needed to do an export.