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, 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)
 

Detailed Description

Definition at line 280 of file ExportCL.cpp.

Constructor & Destructor Documentation

ExportCL::ExportCL ( )

Definition at line 300 of file ExportCL.cpp.

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

301 : ExportPlugin()
302 {
303  AddFormat();
304  SetFormat(wxT("CL"),0);
305  AddExtension(wxT(""),0);
306  SetMaxChannels(255,0);
307  SetCanMetaData(false,0);
308  SetDescription(_("(external program)"),0);
309 }
void SetDescription(const wxString &description, int index)
Definition: Export.cpp:124
void SetFormat(const wxString &format, int index)
Definition: Export.cpp:119
void SetMaxChannels(unsigned maxchannels, unsigned index)
Definition: Export.cpp:144
ExportPlugin()
Definition: Export.cpp:81
_("Move Track &Down")+wxT("\t")+(GetActiveProject() -> GetCommandManager() ->GetKeyFromName(wxT("TrackMoveDown"))), OnMoveTrack) POPUP_MENU_ITEM(OnMoveTopID, _("Move Track to &Top")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveTop"))), OnMoveTrack) POPUP_MENU_ITEM(OnMoveBottomID, _("Move Track to &Bottom")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveBottom"))), OnMoveTrack) void TrackMenuTable::OnSetName(wxCommandEvent &)
int AddFormat()
Add a NEW entry to the list of formats this plug-in can export.
Definition: Export.cpp:103
void SetCanMetaData(bool canmetadata, int index)
Definition: Export.cpp:149
void AddExtension(const wxString &extension, int index)
Definition: Export.cpp:129

Member Function Documentation

ProgressResult ExportCL::Export ( AudacityProject project,
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
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.

Implements ExportPlugin.

Definition at line 311 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, wav_header::fmtID, wav_header::formatChunkLen, wav_header::formatTag, AudacityProject::GetRate(), ExportCLProcess::GetStatus(), TrackList::GetTimeTrack(), AudacityProject::GetTracks(), TrackList::GetWaveTrackConstArray(), gPrefs, ShuttleGui::Id(), ExportCLProcess::IsActive(), wav_header::lenAfterRiff, lrint, wav_header::riffID, wav_header::riffType, wav_header::sampleRate, ShuttleGuiBase::StartHorizontalLay(), Success, and ProgressDialog::Update().

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

Implements ExportPlugin.

Definition at line 537 of file ExportCL.cpp.

References safenew.

538 {
539  wxASSERT(parent); // to justify safenew
540  return safenew ExportCLOptions(parent, format);
541 }
#define safenew
Definition: Audacity.h:223
int format
Definition: ExportPCM.cpp:56

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