Audacity  2.2.2
Public Member Functions | List of all members
ExportCL Class Referencefinal
Inheritance diagram for ExportCL:
ExportPlugin

Public Member Functions

 ExportCL ()
 
wxWindow * OptionsCreate (wxWindow *parent, int format) override
 
ProgressResult Export (AudacityProject *project, std::unique_ptr< ProgressDialog > &pDialog, unsigned channels, const wxString &fName, bool selectedOnly, double t0, double t1, MixerSpec *mixerSpec=NULL, const Tags *metadata=NULL, int subformat=0) override
 called to export audio into a file. More...
 
- Public Member Functions inherited from ExportPlugin
 ExportPlugin ()
 
virtual ~ExportPlugin ()
 
int AddFormat ()
 Add a NEW entry to the list of formats this plug-in can export. More...
 
void SetFormat (const wxString &format, int index)
 
void SetDescription (const wxString &description, int index)
 
void AddExtension (const wxString &extension, int index)
 
void SetExtensions (const wxArrayString &extensions, int index)
 
void SetMask (const wxString &mask, int index)
 
void SetMaxChannels (unsigned maxchannels, unsigned index)
 
void SetCanMetaData (bool canmetadata, int index)
 
virtual int GetFormatCount ()
 
virtual wxString GetFormat (int index)
 
virtual wxString GetDescription (int index)
 
virtual wxString GetExtension (int index=0)
 Return the (first) file name extension for the sub-format. More...
 
virtual wxArrayString GetExtensions (int index=0)
 Return all the file name extensions used for the sub-format. More...
 
virtual wxString GetMask (int index)
 
virtual unsigned GetMaxChannels (int index)
 
virtual bool GetCanMetaData (int index)
 
virtual bool IsExtension (const wxString &ext, int index)
 
virtual bool DisplayOptions (wxWindow *parent, int format=0)
 
virtual bool CheckFileName (wxFileName &filename, int format=0)
 
virtual int SetNumExportChannels ()
 Exporter plug-ins may override this to specify the number of channels in exported file. -1 for unspecified. More...
 

Additional Inherited Members

- Protected Member Functions inherited from ExportPlugin
std::unique_ptr< MixerCreateMixer (const WaveTrackConstArray &inputTracks, const TimeTrack *timeTrack, double startTime, double stopTime, unsigned numOutChannels, size_t outBufferSize, bool outInterleaved, double outRate, sampleFormat outFormat, bool highQuality=true, MixerSpec *mixerSpec=NULL)
 
- Static Protected Member Functions inherited from ExportPlugin
static void InitProgress (std::unique_ptr< ProgressDialog > &pDialog, const wxString &title, const wxString &message)
 

Detailed Description

Definition at line 280 of file ExportCL.cpp.

Constructor & Destructor Documentation

ExportCL::ExportCL ( )

Definition at line 301 of file ExportCL.cpp.

References _(), ExportPlugin::AddExtension(), ExportPlugin::AddFormat(), ExportPlugin::SetCanMetaData(), ExportPlugin::SetDescription(), ExportPlugin::SetFormat(), and ExportPlugin::SetMaxChannels().

302 : ExportPlugin()
303 {
304  AddFormat();
305  SetFormat(wxT("CL"),0);
306  AddExtension(wxT(""),0);
307  SetMaxChannels(255,0);
308  SetCanMetaData(false,0);
309  SetDescription(_("(external program)"),0);
310 }
void SetDescription(const wxString &description, int index)
Definition: Export.cpp:120
void SetFormat(const wxString &format, int index)
Definition: Export.cpp:115
void SetMaxChannels(unsigned maxchannels, unsigned index)
Definition: Export.cpp:140
ExportPlugin()
Definition: Export.cpp:79
_("Move Track &Down")+wxT("\t")+(GetActiveProject() -> GetCommandManager() ->GetKeyFromName(wxT("TrackMoveDown")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveTopID, _("Move Track to &Top")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveTop")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveBottomID, _("Move Track to &Bottom")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveBottom")).Raw()), OnMoveTrack)#define SET_TRACK_NAME_PLUGIN_SYMBOLclass SetTrackNameCommand:public AudacityCommand
int AddFormat()
Add a NEW entry to the list of formats this plug-in can export.
Definition: Export.cpp:99
void SetCanMetaData(bool canmetadata, int index)
Definition: Export.cpp:145
void AddExtension(const wxString &extension, int index)
Definition: Export.cpp:125

Member Function Documentation

ProgressResult ExportCL::Export ( AudacityProject project,
std::unique_ptr< ProgressDialog > &  pDialog,
unsigned  channels,
const wxString &  fName,
bool  selectedOnly,
double  t0,
double  t1,
MixerSpec mixerSpec = NULL,
const Tags metadata = NULL,
int  subformat = 0 
)
overridevirtual

called to export audio into a file.

Parameters
pDialogTo be initialized with pointer to a NEW ProgressDialog if it was null, otherwise gives an existing dialog to be reused (working around a problem in wxWidgets for Mac; see bug 1600)
selectedOnlySet to true if all tracks should be mixed, to false if only the selected tracks should be mixed and exported.
metadataA Tags object that will over-ride the one in *project and be used to tag the file that is exported.
subformatControl which of the multiple formats this exporter is capable of exporting should be used. Used where a single export plug-in handles a number of related formats, but they have separate entries in the Format drop-down list box. For example, the options to export to "Other PCM", "AIFF 16 Bit" and "WAV 16 Bit" are all the same libsndfile export plug-in, but with subformat set to 0, 1, and 2 respectively.
Returns
ProgressResult::Failed or ProgressResult::Cancelled if export fails to complete for any reason, in which case this function is responsible for alerting the user. Otherwise ProgressResult::Success or ProgressResult::Stopped

Implements ExportPlugin.

Definition at line 312 of file ExportCL.cpp.

References _(), ShuttleGuiBase::AddButton(), ShuttleGuiBase::AddTextWindow(), AudacityMessageBox(), wav_header::avgBytesPerSec, wav_header::bitsPerSample, wav_header::blockAlign, Cancelled, wav_header::channels, ExportPlugin::CreateMixer(), wav_header::dataID, wav_header::dataLen, Drain(), eIsCreating, Failed, wav_header::fmtID, wav_header::formatChunkLen, wav_header::formatTag, AudacityProject::GetRate(), ExportCLProcess::GetStatus(), TrackList::GetTimeTrack(), AudacityProject::GetTracks(), TrackList::GetWaveTrackConstArray(), gPrefs, ShuttleGui::Id(), ExportPlugin::InitProgress(), int16Sample, ExportCLProcess::IsActive(), wav_header::lenAfterRiff, lrint, wav_header::riffID, wav_header::riffType, SAMPLE_SIZE, wav_header::sampleRate, ShuttleGuiBase::StartHorizontalLay(), and Success.

322 {
323  wxString output;
324  wxString cmd;
325  bool show;
326  long rc;
327 
328  // Retrieve settings
329  gPrefs->Read(wxT("/FileFormats/ExternalProgramShowOutput"), &show, false);
330  cmd = gPrefs->Read(wxT("/FileFormats/ExternalProgramExportCommand"), wxT("lame - \"%f.mp3\""));
331  cmd.Replace(wxT("%f"), fName);
332 
333 #if defined(__WXMSW__)
334  // Give Windows a chance at finding lame command in the default location.
335  wxString paths[] = {wxT("HKEY_LOCAL_MACHINE\\Software\\Lame for Audacity"),
336  wxT("HKEY_LOCAL_MACHINE\\Software\\FFmpeg for Audacity")};
337  wxString opath;
338  wxString npath;
339  wxRegKey reg;
340 
341  wxGetEnv(wxT("PATH"), &opath);
342  npath = opath;
343 
344  for (int i = 0; i < WXSIZEOF(paths); i++) {
345  reg.SetName(paths[i]);
346 
347  if (reg.Exists()) {
348  wxString ipath;
349  reg.QueryValue(wxT("InstallPath"), ipath);
350  if (!ipath.IsEmpty()) {
351  npath += wxPATH_SEP + ipath;
352  }
353  }
354  }
355 
356  wxSetEnv(wxT("PATH"),npath);
357 #endif
358 
359  // Kick off the command
360  ExportCLProcess process(&output);
361 
362  {
363 #if defined(__WXMSW__)
364  auto cleanup = finally( [&] {
365  if (!opath.IsEmpty()) {
366  wxSetEnv(wxT("PATH"),opath);
367  }
368  } );
369 #endif
370 
371  rc = wxExecute(cmd, wxEXEC_ASYNC, &process);
372  }
373 
374  if (!rc) {
375  AudacityMessageBox(wxString::Format(_("Cannot export audio to %s"),
376  fName));
377  process.Detach();
378  process.CloseOutput();
379 
381  }
382 
383  // Turn off logging to prevent broken pipe messages
384  wxLogNull nolog;
385 
386  // establish parameters
387  int rate = lrint(project->GetRate());
388  const size_t maxBlockLen = 44100 * 5;
389  unsigned long totalSamples = lrint((t1 - t0) * rate);
390  unsigned long sampleBytes = totalSamples * channels * SAMPLE_SIZE(int16Sample);
391 
392  // fill up the wav header
393  wav_header header;
394  header.riffID[0] = 'R';
395  header.riffID[1] = 'I';
396  header.riffID[2] = 'F';
397  header.riffID[3] = 'F';
398  header.lenAfterRiff = wxUINT32_SWAP_ON_BE(sampleBytes + 36);
399  header.riffType[0] = 'W';
400  header.riffType[1] = 'A';
401  header.riffType[2] = 'V';
402  header.riffType[3] = 'E';
403 
404  header.fmtID[0] = 'f';
405  header.fmtID[1] = 'm';
406  header.fmtID[2] = 't';
407  header.fmtID[3] = ' ';
408  header.formatChunkLen = wxUINT32_SWAP_ON_BE(16);
409  header.formatTag = wxUINT16_SWAP_ON_BE(1);
410  header.channels = wxUINT16_SWAP_ON_BE(channels);
411  header.sampleRate = wxUINT32_SWAP_ON_BE(rate);
412  header.bitsPerSample = wxUINT16_SWAP_ON_BE(SAMPLE_SIZE(int16Sample) * 8);
413  header.blockAlign = wxUINT16_SWAP_ON_BE(header.bitsPerSample * header.channels / 8);
414  header.avgBytesPerSec = wxUINT32_SWAP_ON_BE(header.sampleRate * header.blockAlign);
415  header.dataID[0] = 'd';
416  header.dataID[1] = 'a';
417  header.dataID[2] = 't';
418  header.dataID[3] = 'a';
419  header.dataLen = wxUINT32_SWAP_ON_BE(sampleBytes);
420 
421  // write the header
422  wxOutputStream *os = process.GetOutputStream();
423  os->Write(&header, sizeof(wav_header));
424 
425  // Mix 'em up
426  const TrackList *tracks = project->GetTracks();
427  const WaveTrackConstArray waveTracks =
428  tracks->GetWaveTrackConstArray(selectionOnly, false);
429  auto mixer = CreateMixer(
430  waveTracks,
431  tracks->GetTimeTrack(),
432  t0,
433  t1,
434  channels,
435  maxBlockLen,
436  true,
437  rate,
438  int16Sample,
439  true,
440  mixerSpec);
441 
442  size_t numBytes = 0;
443  samplePtr mixed = NULL;
444  auto updateResult = ProgressResult::Success;
445 
446  {
447  auto closeIt = finally ( [&] {
448  // Should make the process die, before propagating any exception
449  process.CloseOutput();
450  } );
451 
452  // Prepare the progress display
453  InitProgress( pDialog, _("Export"),
454  selectionOnly
455  ? _("Exporting the selected audio using command-line encoder")
456  : _("Exporting the audio using command-line encoder") );
457  auto &progress = *pDialog;
458 
459  // Start piping the mixed data to the command
460  while (updateResult == ProgressResult::Success && process.IsActive() && os->IsOk()) {
461  // Capture any stdout and stderr from the command
462  Drain(process.GetInputStream(), &output);
463  Drain(process.GetErrorStream(), &output);
464 
465  // Need to mix another block
466  if (numBytes == 0) {
467  auto numSamples = mixer->Process(maxBlockLen);
468  if (numSamples == 0) {
469  break;
470  }
471 
472  mixed = mixer->GetBuffer();
473  numBytes = numSamples * channels;
474 
475  // Byte-swapping is neccesary on big-endian machines, since
476  // WAV files are little-endian
477 #if wxBYTE_ORDER == wxBIG_ENDIAN
478  wxUint16 *buffer = (wxUint16 *) mixed;
479  for (int i = 0; i < numBytes; i++) {
480  buffer[i] = wxUINT16_SWAP_ON_BE(buffer[i]);
481  }
482 #endif
483  numBytes *= SAMPLE_SIZE(int16Sample);
484  }
485 
486  // Don't write too much at once...pipes may not be able to handle it
487  size_t bytes = wxMin(numBytes, 4096);
488  numBytes -= bytes;
489 
490  while (bytes > 0) {
491  os->Write(mixed, bytes);
492  if (!os->IsOk()) {
493  updateResult = ProgressResult::Cancelled;
494  break;
495  }
496  bytes -= os->LastWrite();
497  mixed += os->LastWrite();
498  }
499 
500  // Update the progress display
501  updateResult = progress.Update(mixer->MixGetCurrentTime() - t0, t1 - t0);
502  }
503  // Done with the progress display
504  }
505 
506  // Wait for process to terminate
507  while (process.IsActive()) {
508  wxMilliSleep(10);
509  wxTheApp->Yield();
510  }
511 
512  // Display output on error or if the user wants to see it
513  if (process.GetStatus() != 0 || show) {
514  // TODO use ShowInfoDialog() instead.
515  wxDialogWrapper dlg(nullptr,
516  wxID_ANY,
517  wxString(_("Command Output")),
518  wxDefaultPosition,
519  wxSize(600, 400),
520  wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER);
521  dlg.SetName(dlg.GetTitle());
522 
523  ShuttleGui S(&dlg, eIsCreating);
524  S.AddTextWindow(cmd + wxT("\n\n") + output);
525  S.StartHorizontalLay(wxALIGN_CENTER, false);
526  {
527  S.Id(wxID_OK).AddButton(_("&OK"))->SetDefault();
528  }
529  dlg.GetSizer()->AddSpacer(5);
530  dlg.Layout();
531  dlg.SetMinSize(dlg.GetSize());
532  dlg.Center();
533 
534  dlg.ShowModal();
535 
536  if (process.GetStatus() != 0)
537  updateResult = ProgressResult::Failed;
538  }
539 
540  return updateResult;
541 }
AudacityPrefs * gPrefs
Definition: Prefs.cpp:73
A list of TrackListNode items.
Definition: Track.h:623
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI...
Definition: ShuttleGui.h:409
#define SAMPLE_SIZE(SampleFormat)
Definition: Types.h:198
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
wxUint16 bitsPerSample
Definition: ExportCL.cpp:273
wxUint32 dataLen
Definition: ExportCL.cpp:277
std::unique_ptr< Mixer > CreateMixer(const WaveTrackConstArray &inputTracks, const TimeTrack *timeTrack, double startTime, double stopTime, unsigned numOutChannels, size_t outBufferSize, bool outInterleaved, double outRate, sampleFormat outFormat, bool highQuality=true, MixerSpec *mixerSpec=NULL)
Definition: Export.cpp:237
TimeTrack * GetTimeTrack()
Definition: Track.cpp:1244
wxUint16 blockAlign
Definition: ExportCL.cpp:272
WaveTrackConstArray GetWaveTrackConstArray(bool selectionOnly, bool includeMuted=true) const
Definition: Track.cpp:1349
std::vector< std::shared_ptr< const WaveTrack > > WaveTrackConstArray
Definition: AudioIO.h:68
char riffType[4]
Definition: ExportCL.cpp:263
#define lrint(dbl)
Definition: float_cast.h:136
char * samplePtr
Definition: Types.h:203
char fmtID[4]
Definition: ExportCL.cpp:266
char dataID[4]
Definition: ExportCL.cpp:276
_("Move Track &Down")+wxT("\t")+(GetActiveProject() -> GetCommandManager() ->GetKeyFromName(wxT("TrackMoveDown")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveTopID, _("Move Track to &Top")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveTop")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveBottomID, _("Move Track to &Bottom")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveBottom")).Raw()), OnMoveTrack)#define SET_TRACK_NAME_PLUGIN_SYMBOLclass SetTrackNameCommand:public AudacityCommand
char riffID[4]
Definition: ExportCL.cpp:261
wxUint32 sampleRate
Definition: ExportCL.cpp:270
wxUint32 lenAfterRiff
Definition: ExportCL.cpp:262
wxUint32 avgBytesPerSec
Definition: ExportCL.cpp:271
wxUint16 channels
Definition: ExportCL.cpp:269
wxUint32 formatChunkLen
Definition: ExportCL.cpp:267
double GetRate() const
Definition: Project.h:199
TrackList * GetTracks()
Definition: Project.h:192
wxUint16 formatTag
Definition: ExportCL.cpp:268
static void InitProgress(std::unique_ptr< ProgressDialog > &pDialog, const wxString &title, const wxString &message)
Definition: Export.cpp:255
static void Drain(wxInputStream *s, wxString *o)
Definition: ExportCL.cpp:201
wxWindow * ExportCL::OptionsCreate ( wxWindow *  parent,
int  format 
)
overridevirtual

Implements ExportPlugin.

Definition at line 543 of file ExportCL.cpp.

References safenew.

544 {
545  wxASSERT(parent); // to justify safenew
546  return safenew ExportCLOptions(parent, format);
547 }
#define safenew
Definition: Audacity.h:230
int format
Definition: ExportPCM.cpp:56

The documentation for this class was generated from the following file: