1 /********************************************************************** 2 3 Audacity: A Digital Audio Editor 4 5 Export.h 6 7 Dominic Mazzoni 8 9 **********************************************************************/ 10 11 #ifndef __AUDACITY_EXPORT__ 12 #define __AUDACITY_EXPORT__ 13 14 #include <functional> 15 #include <vector> 16 #include <wx/filename.h> // member variable 17 #include "Identifier.h" 18 #include "SampleFormat.h" 19 #include "../widgets/wxPanelWrapper.h" // to inherit 20 #include "FileNames.h" // for FileTypes 21 22 #include "Registry.h" 23 24 class wxArrayString; 25 class FileDialogWrapper; 26 class wxFileCtrlEvent; 27 class wxMemoryDC; 28 class wxSimplebook; 29 class wxStaticText; 30 class AudacityProject; 31 class WaveTrack; 32 class Tags; 33 class TrackList; 34 class MixerSpec; 35 class ProgressDialog; 36 class ShuttleGui; 37 class Mixer; 38 using WaveTrackConstArray = std::vector < std::shared_ptr < const WaveTrack > >; 39 namespace BasicUI{ enum class ProgressResult : unsigned; } 40 class wxFileNameWrapper; 41 42 class AUDACITY_DLL_API FormatInfo 43 { 44 public: FormatInfo()45 FormatInfo() {} 46 FormatInfo( const FormatInfo & ) = default; 47 FormatInfo &operator = ( const FormatInfo & ) = default; 48 //FormatInfo( FormatInfo && ) = default; 49 //FormatInfo &operator = ( FormatInfo && ) = default; ~FormatInfo()50 ~FormatInfo() {} 51 52 wxString mFormat; 53 TranslatableString mDescription; 54 // wxString mExtension; 55 FileExtensions mExtensions; 56 FileNames::FileTypes mMask; 57 unsigned mMaxChannels; 58 bool mCanMetaData; 59 }; 60 61 //---------------------------------------------------------------------------- 62 // ExportPlugin 63 //---------------------------------------------------------------------------- 64 class AUDACITY_DLL_API ExportPlugin /* not final */ 65 { 66 public: 67 using ProgressResult = BasicUI::ProgressResult; 68 69 ExportPlugin(); 70 virtual ~ExportPlugin(); 71 72 int AddFormat(); 73 void SetFormat(const wxString & format, int index); 74 void SetDescription(const TranslatableString & description, int index); 75 void AddExtension(const FileExtension &extension, int index); 76 void SetExtensions(FileExtensions extensions, int index); 77 void SetMask(FileNames::FileTypes mask, int index); 78 void SetMaxChannels(unsigned maxchannels, unsigned index); 79 void SetCanMetaData(bool canmetadata, int index); 80 81 virtual int GetFormatCount(); 82 virtual wxString GetFormat(int index); 83 TranslatableString GetDescription(int index); 84 /** @brief Return the (first) file name extension for the sub-format. 85 * @param index The sub-format for which the extension is wanted */ 86 virtual FileExtension GetExtension(int index = 0); 87 /** @brief Return all the file name extensions used for the sub-format. 88 * @param index the sub-format for which the extension is required */ 89 virtual FileExtensions GetExtensions(int index = 0); 90 FileNames::FileTypes GetMask(int index); 91 virtual unsigned GetMaxChannels(int index); 92 virtual bool GetCanMetaData(int index); 93 94 virtual bool IsExtension(const FileExtension & ext, int index); 95 96 virtual bool DisplayOptions(wxWindow *parent, int format = 0); 97 98 virtual void OptionsCreate(ShuttleGui &S, int format) = 0; 99 100 virtual bool CheckFileName(wxFileName &filename, int format = 0); 101 /** @brief Exporter plug-ins may override this to specify the number 102 * of channels in exported file. -1 for unspecified */ SetNumExportChannels()103 virtual int SetNumExportChannels() { return -1; } 104 105 /** \brief called to export audio into a file. 106 * 107 * @param pDialog To be initialized with pointer to a NEW ProgressDialog if 108 * it was null, otherwise gives an existing dialog to be reused 109 * (working around a problem in wxWidgets for Mac; see bug 1600) 110 * @param selectedOnly Set to true if all tracks should be mixed, to false 111 * if only the selected tracks should be mixed and exported. 112 * @param metadata A Tags object that will over-ride the one in *project and 113 * be used to tag the file that is exported. 114 * @param subformat Control which of the multiple formats this exporter is 115 * capable of exporting should be used. Used where a single export plug-in 116 * handles a number of related formats, but they have separate 117 * entries in the Format drop-down list box. For example, the options to 118 * export to "Other PCM", "AIFF 16 Bit" and "WAV 16 Bit" are all the same 119 * libsndfile export plug-in, but with subformat set to 0, 1, and 2 120 * respectively. 121 * @return ProgressResult::Failed or ProgressResult::Cancelled if export 122 * fails to complete for any reason, in which case this function is 123 * responsible for alerting the user. Otherwise ProgressResult::Success or 124 * ProgressResult::Stopped 125 */ 126 virtual ProgressResult Export(AudacityProject *project, 127 std::unique_ptr<ProgressDialog> &pDialog, 128 unsigned channels, 129 const wxFileNameWrapper &fName, 130 bool selectedOnly, 131 double t0, 132 double t1, 133 MixerSpec *mixerSpec = NULL, 134 const Tags *metadata = NULL, 135 int subformat = 0) = 0; 136 137 protected: 138 std::unique_ptr<Mixer> CreateMixer(const TrackList &tracks, 139 bool selectionOnly, 140 double startTime, double stopTime, 141 unsigned numOutChannels, size_t outBufferSize, bool outInterleaved, 142 double outRate, sampleFormat outFormat, 143 MixerSpec *mixerSpec); 144 145 // Create or recycle a dialog. 146 static void InitProgress(std::unique_ptr<ProgressDialog> &pDialog, 147 const TranslatableString &title, const TranslatableString &message); 148 static void InitProgress(std::unique_ptr<ProgressDialog> &pDialog, 149 const wxFileNameWrapper &title, const TranslatableString &message); 150 151 private: 152 std::vector<FormatInfo> mFormatInfos; 153 }; 154 155 using ExportPluginArray = std::vector < std::unique_ptr< ExportPlugin > > ; 156 157 //---------------------------------------------------------------------------- 158 // Exporter 159 //---------------------------------------------------------------------------- 160 161 // For a file suffix change from the options. 162 wxDECLARE_EXPORTED_EVENT(AUDACITY_DLL_API, 163 AUDACITY_FILE_SUFFIX_EVENT, wxCommandEvent); 164 165 class AUDACITY_DLL_API Exporter final : public wxEvtHandler 166 { 167 public: 168 169 using ExportPluginFactory = 170 std::function< std::unique_ptr< ExportPlugin >() >; 171 172 // Objects of this type are statically constructed in files implementing 173 // subclasses of ExportPlugin 174 // Register factories, not plugin objects themselves, which allows them 175 // to have some fresh state variables each time export begins again 176 // and to compute translated strings for the current locale 177 struct AUDACITY_DLL_API RegisteredExportPlugin{ 178 RegisteredExportPlugin( 179 const Identifier &id, // an internal string naming the plug-in 180 const ExportPluginFactory&, 181 const Registry::Placement &placement = { wxEmptyString, {} } ); 182 }; 183 184 static bool DoEditMetadata(AudacityProject &project, 185 const TranslatableString &title, 186 const TranslatableString &shortUndoDescription, bool force); 187 188 Exporter( AudacityProject &project ); 189 virtual ~Exporter(); 190 191 void SetFileDialogTitle( const TranslatableString & DialogTitle ); SetDefaultFormat(const FileExtension & Format)192 void SetDefaultFormat( const FileExtension & Format ){ mFormatName = Format;}; 193 194 bool Process(bool selectedOnly, 195 double t0, double t1); 196 bool Process(unsigned numChannels, 197 const FileExtension &type, const wxString & filename, 198 bool selectedOnly, double t0, double t1); 199 200 void DisplayOptions(int index); 201 int FindFormatIndex(int exportindex); 202 203 const ExportPluginArray &GetPlugins(); 204 205 // Auto Export from Timer Recording 206 bool ProcessFromTimerRecording(bool selectedOnly, 207 double t0, 208 double t1, 209 wxFileName fnFile, 210 int iFormat, 211 int iSubFormat, 212 int iFilterIndex); 213 bool SetAutoExportOptions(); 214 int GetAutoExportFormat(); 215 int GetAutoExportSubFormat(); 216 int GetAutoExportFilterIndex(); 217 wxFileName GetAutoExportFileName(); 218 void OnExtensionChanged(wxCommandEvent &evt); 219 void OnHelp(wxCommandEvent &evt); 220 221 private: 222 bool ExamineTracks(); 223 bool GetFilename(); 224 bool CheckFilename(); 225 bool CheckMix(bool prompt = true); 226 bool ExportTracks(); 227 228 static void CreateUserPaneCallback(wxWindow *parent, wxUIntPtr userdata); 229 void CreateUserPane(wxWindow *parent); 230 void OnFilterChanged(wxFileCtrlEvent & evt); 231 232 private: 233 FileExtension mFormatName; 234 FileDialogWrapper *mDialog; 235 TranslatableString mFileDialogTitle; 236 AudacityProject *mProject; 237 std::unique_ptr<MixerSpec> mMixerSpec; 238 239 ExportPluginArray mPlugins; 240 241 wxFileName mFilename; 242 wxFileName mActualName; 243 244 double mT0; 245 double mT1; 246 int mFilterIndex; 247 int mFormat; 248 int mSubFormat; 249 int mNumSelected; 250 unsigned mNumLeft; 251 unsigned mNumRight; 252 unsigned mNumMono; 253 unsigned mChannels; 254 bool mSelectedOnly; 255 256 wxSimplebook *mBook; 257 258 DECLARE_EVENT_TABLE() 259 }; 260 261 //---------------------------------------------------------------------------- 262 // ExportMixerPanel 263 //---------------------------------------------------------------------------- 264 class ExportMixerPanel final : public wxPanelWrapper 265 { 266 public: 267 ExportMixerPanel( wxWindow *parent, wxWindowID id, 268 MixerSpec *mixerSpec, wxArrayString trackNames, 269 const wxPoint& pos = wxDefaultPosition, 270 const wxSize& size = wxDefaultSize); 271 virtual ~ExportMixerPanel(); 272 273 void OnMouseEvent(wxMouseEvent & event); 274 void OnPaint(wxPaintEvent & event); 275 276 private: 277 std::unique_ptr<wxBitmap> mBitmap; 278 wxRect mEnvRect; 279 int mWidth; 280 int mHeight; 281 MixerSpec *mMixerSpec; 282 ArrayOf<wxRect> mChannelRects; 283 ArrayOf<wxRect> mTrackRects; 284 int mSelectedTrack, mSelectedChannel; 285 wxArrayString mTrackNames; 286 int mBoxWidth, mChannelHeight, mTrackHeight; 287 288 void SetFont( wxMemoryDC &memDC, const wxString &text, int width, int height ); 289 double Distance( wxPoint &a, wxPoint &b ); 290 bool IsOnLine( wxPoint p, wxPoint la, wxPoint lb ); 291 292 DECLARE_EVENT_TABLE() 293 }; 294 295 //---------------------------------------------------------------------------- 296 // ExportMixerDialog 297 //---------------------------------------------------------------------------- 298 class ExportMixerDialog final : public wxDialogWrapper 299 { 300 public: 301 // constructors and destructors 302 ExportMixerDialog( const TrackList * tracks, bool selectedOnly, unsigned maxNumChannels, 303 wxWindow *parent, wxWindowID id, const TranslatableString &title, 304 const wxPoint& pos = wxDefaultPosition, 305 const wxSize& size = wxDefaultSize, 306 long style = wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER ); 307 virtual ~ExportMixerDialog(); 308 GetMixerSpec()309 MixerSpec* GetMixerSpec() { return mMixerSpec.get(); } 310 311 private: 312 wxStaticText *mChannelsText; 313 std::unique_ptr<MixerSpec> mMixerSpec; 314 wxArrayString mTrackNames; 315 316 private: 317 void OnOk( wxCommandEvent &event ); 318 void OnCancel( wxCommandEvent &event ); 319 void OnMixerPanelHelp( wxCommandEvent &event ); 320 void OnSlider( wxCommandEvent &event ); 321 void OnSize( wxSizeEvent &event ); 322 323 private: 324 DECLARE_EVENT_TABLE() 325 }; 326 327 AUDACITY_DLL_API TranslatableString AudacityExportCaptionStr(); 328 AUDACITY_DLL_API TranslatableString AudacityExportMessageStr(); 329 330 /// We have many Export errors that are essentially anonymous 331 /// and are distinguished only by an error code number. 332 /// Rather than repeat the code, we have it just once. 333 AUDACITY_DLL_API void ShowExportErrorDialog(wxString ErrorCode, 334 TranslatableString message = AudacityExportMessageStr(), 335 const TranslatableString& caption = AudacityExportCaptionStr(), 336 bool allowReporting = true); 337 338 AUDACITY_DLL_API 339 void ShowDiskFullExportErrorDialog(const wxFileNameWrapper &fileName); 340 341 #endif 342