Audacity  3.0.3
ImportAUP.cpp
Go to the documentation of this file.
1 /*!********************************************************************
2 
3  Audacity: A Digital Audio Editor
4 
5  @file ImportAUP.cpp
6  @brief Upgrading project file formats from before version 3
7 
8 *//****************************************************************//****************************************************************//*******************************************************************/
19 
20 
21 
22 #include "Import.h"
23 #include "ImportPlugin.h"
24 
25 #include "../Envelope.h"
26 #include "../FileFormats.h"
27 #include "../FileNames.h"
28 #include "../LabelTrack.h"
29 #if defined(USE_MIDI)
30 #include "../NoteTrack.h"
31 #endif
32 #include "Prefs.h"
33 #include "../Project.h"
34 #include "../ProjectFileIO.h"
35 #include "../ProjectFileManager.h"
36 #include "../ProjectHistory.h"
37 #include "../ProjectSelectionManager.h"
38 #include "../ProjectSettings.h"
39 #include "../Sequence.h"
40 #include "../Tags.h"
41 #include "../TimeTrack.h"
42 #include "../ViewInfo.h"
43 #include "../WaveClip.h"
44 #include "../WaveTrack.h"
45 #include "../toolbars/SelectionBar.h"
46 #include "../widgets/AudacityMessageBox.h"
47 #include "../widgets/NumericTextCtrl.h"
48 #include "../widgets/ProgressDialog.h"
49 #include "../xml/XMLFileReader.h"
50 #include "../wxFileNameWrapper.h"
51 
52 #include <map>
53 
54 #define DESC XO("AUP project files (*.aup)")
55 
56 static const auto exts = {wxT("aup")};
57 
58 #include <wx/dir.h>
59 #include <wx/ffile.h>
60 #include <wx/file.h>
61 #include <wx/frame.h>
62 #include <wx/log.h>
63 #include <wx/string.h>
64 #include <wx/utils.h>
65 
67 using ImportHandle = std::unique_ptr<ImportFileHandle>;
68 
69 using NewChannelGroup = std::vector<std::shared_ptr<WaveTrack>>;
70 
71 class AUPImportPlugin final : public ImportPlugin
72 {
73 public:
76 
77  wxString GetPluginStringID() override;
78 
80 
81  ImportHandle Open(const FilePath &fileName,
82  AudacityProject *project) override;
83 };
84 
86  public XMLTagHandler
87 {
88 public:
90  AudacityProject *project);
92 
94 
96 
98  TrackHolders &outTracks,
99  Tags *tags) override;
100 
101  wxInt32 GetStreamCount() override;
102 
103  const TranslatableStrings &GetStreamInfo() override;
104 
105  void SetStreamUsage(wxInt32 WXUNUSED(StreamID), bool WXUNUSED(Use)) override;
106 
107  bool Open();
108 
109 private:
110  struct node
111  {
112  wxString parent;
113  wxString tag;
115  };
116  using stack = std::vector<struct node>;
117 
118  bool HandleXMLTag(const wxChar *tag, const wxChar **attrs) override;
119  void HandleXMLEndTag(const wxChar *tag) override;
120  XMLTagHandler *HandleXMLChild(const wxChar *tag) override;
121 
122  bool HandleProject(XMLTagHandler *&handle);
123  bool HandleLabelTrack(XMLTagHandler *&handle);
124  bool HandleNoteTrack(XMLTagHandler *&handle);
125  bool HandleTimeTrack(XMLTagHandler *&handle);
126  bool HandleWaveTrack(XMLTagHandler *&handle);
127  bool HandleTags(XMLTagHandler *&handle);
128  bool HandleTag(XMLTagHandler *&handle);
129  bool HandleLabel(XMLTagHandler *&handle);
130  bool HandleWaveClip(XMLTagHandler *&handle);
131  bool HandleSequence(XMLTagHandler *&handle);
132  bool HandleWaveBlock(XMLTagHandler *&handle);
133  bool HandleEnvelope(XMLTagHandler *&handle);
134  bool HandleControlPoint(XMLTagHandler *&handle);
135  bool HandleSimpleBlockFile(XMLTagHandler *&handle);
136  bool HandleSilentBlockFile(XMLTagHandler *&handle);
137  bool HandlePCMAliasBlockFile(XMLTagHandler *&handle);
138  bool HandleImport(XMLTagHandler *&handle);
139 
140  // Called in first pass to collect information about blocks
141  void AddFile(sampleCount len,
143  const FilePath &blockFilename = wxEmptyString,
144  const FilePath &audioFilename = wxEmptyString,
145  sampleCount origin = 0,
146  int channel = 0);
147 
148  // These two use the collected file information in a second pass
149  bool AddSilence(sampleCount len);
150  bool AddSamples(const FilePath &blockFilename,
151  const FilePath &audioFilename,
152  sampleCount len,
154  sampleCount origin = 0,
155  int channel = 0);
156 
157  bool SetError(const TranslatableString &msg);
158  bool SetWarning(const TranslatableString &msg);
159 
160 private:
163 
164  // project tag values that will be set in the actual project if the
165  // import is successful
166  #define field(n, t) bool have##n; t n
167  struct
168  {
169  field(vpos, int);
170  field(h, double);
171  field(zoom, double);
172  field(sel0, double);
173  field(sel1, double);
174 #ifdef EXPERIMENTAL_SPECTRAL_EDITING
175  field(selLow, double) = SelectedRegion::UndefinedFrequency;
176  field(selHigh, double) = SelectedRegion::UndefinedFrequency;
177 #endif
178  field(rate, double);
179  field(snapto, bool);
180  field(selectionformat, wxString);
181  field(audiotimeformat, wxString);
182  field(frequencyformat, wxString);
183  field(bandwidthformat, wxString);
185  #undef field
186 
187  typedef struct
188  {
196  int channel;
197  } fileinfo;
198  std::vector<fileinfo> mFiles;
200 
202  unsigned long mNumChannels;
203 
205  wxString mParentTag;
206  wxString mCurrentTag;
207  const wxChar **mAttrs;
208 
209  wxFileName mProjDir;
210  using BlockFileMap =
211  std::map<wxString, std::pair<FilePath, std::shared_ptr<SampleBlock>>>;
213 
216  std::vector<WaveClip *> mClips;
217 
220 };
221 
223 : ImportPlugin(FileExtensions(exts.begin(), exts.end()))
224 {
225  static_assert(
226  sizeof(long long) >= sizeof(uint64_t) &&
227  sizeof(long) >= sizeof(uint32_t),
228  "Assumptions about sizes in XMLValueChecker calls are invalid!");
229 }
230 
232 {
233 }
234 
236 {
237  return wxT("legacyaup");
238 }
239 
241 {
242  return DESC;
243 }
244 
246  AudacityProject *project)
247 {
248  auto handle = std::make_unique<AUPImportFileHandle>(fileName, project);
249 
250  if (!handle->Open())
251  {
252  // Error or not something that we recognize
253  return nullptr;
254  }
255 
256  return handle;
257 }
258 
260 {
261  "AUP", std::make_unique<AUPImportPlugin>()
262 };
263 
265  AudacityProject *project)
266 : ImportFileHandle(fileName),
267  mProject(*project)
268 {
269 }
270 
272 {
273 }
274 
276 {
277  return DESC;
278 }
279 
281 {
282  // TODO: Get Uncompressed byte count.
283  return 0;
284 }
285 
287  TrackHolders &WXUNUSED(outTracks),
288  Tags *tags)
289 {
290  auto &history = ProjectHistory::Get(mProject);
291  auto &tracks = TrackList::Get(mProject);
292  auto &viewInfo = ViewInfo::Get(mProject);
294  auto &selman = ProjectSelectionManager::Get(mProject);
295 
296  auto oldNumTracks = tracks.size();
297  auto cleanup = finally([this, &tracks, oldNumTracks]{
299  // Revoke additions of tracks
300  while (oldNumTracks < tracks.size()) {
301  Track *lastTrack = *tracks.Any().rbegin();
302  tracks.Remove(lastTrack);
303  }
304  }
305  });
306 
307  bool isDirty = history.GetDirty() || !tracks.empty();
308 
309  mTotalSamples = 0;
310 
311  mTags = tags;
312 
313  CreateProgress();
314 
316 
317  XMLFileReader xmlFile;
318 
319  bool success = xmlFile.Parse(this, mFilename);
320  if (!success)
321  {
323  XO("Couldn't import the project:\n\n%s").Format(xmlFile.GetErrorStr()),
324  XO("Import Project"),
325  wxOK | wxCENTRE,
327 
328  return ProgressResult::Failed;
329  }
330 
331  if (!mErrorMsg.empty())
332  {
333  // Error or warning
335  mErrorMsg,
336  XO("Import Project"),
337  wxOK | wxCENTRE,
339 
340  if (mUpdateResult == ProgressResult::Failed)
341  {
342  // Error
343  return ProgressResult::Failed;
344  }
345  }
346 
347  // If mUpdateResult had been changed, we would have returned already
348  wxASSERT( mUpdateResult == ProgressResult::Success );
349 
350  sampleCount processed = 0;
351  for (auto fi : mFiles)
352  {
355  {
356  return mUpdateResult;
357  }
358 
359  mClip = fi.clip;
360  mWaveTrack = fi.track;
361 
362  if (fi.blockFile.empty())
363  {
364  AddSilence(fi.len);
365  }
366  else
367  {
368  AddSamples(fi.blockFile, fi.audioFile,
369  fi.len, fi.format, fi.origin, fi.channel);
370  }
371 
372  processed += fi.len;
373  }
374 
375  for (auto pClip : mClips)
376  pClip->UpdateEnvelopeTrackLen();
377 
378  wxASSERT( mUpdateResult == ProgressResult::Success );
379 
380  // If the active project is "dirty", then bypass the below updates as we don't
381  // want to going changing things the user may have already set up.
382  if (isDirty)
383  {
384  return mUpdateResult;
385  }
386 
387  if (mProjectAttrs.haverate)
388  {
389  auto &bar = SelectionBar::Get(mProject);
390  bar.SetRate(mProjectAttrs.rate);
391  }
392 
393  if (mProjectAttrs.havesnapto)
394  {
395  selman.AS_SetSnapTo(mProjectAttrs.snapto ? SNAP_NEAREST : SNAP_OFF);
396  }
397 
398  if (mProjectAttrs.haveselectionformat)
399  {
400  selman.AS_SetSelectionFormat(NumericConverter::LookupFormat(NumericConverter::TIME, mProjectAttrs.selectionformat));
401  }
402 
403  if (mProjectAttrs.haveaudiotimeformat)
404  {
405  selman.TT_SetAudioTimeFormat(NumericConverter::LookupFormat(NumericConverter::TIME, mProjectAttrs.audiotimeformat));
406  }
407 
408  if (mProjectAttrs.havefrequencyformat)
409  {
410  selman.SSBL_SetFrequencySelectionFormatName(NumericConverter::LookupFormat(NumericConverter::TIME, mProjectAttrs.frequencyformat));
411  }
412 
413  if (mProjectAttrs.havebandwidthformat)
414  {
415  selman.SSBL_SetBandwidthSelectionFormatName(NumericConverter::LookupFormat(NumericConverter::TIME, mProjectAttrs.bandwidthformat));
416  }
417 
418  // PRL: It seems this must happen after SetSnapTo
419  if (mProjectAttrs.havevpos)
420  {
421  viewInfo.vpos = mProjectAttrs.vpos;
422  }
423 
424  if (mProjectAttrs.haveh)
425  {
426  viewInfo.h = mProjectAttrs.h;
427  }
428 
429  if (mProjectAttrs.havezoom)
430  {
431  viewInfo.SetZoom(mProjectAttrs.zoom);
432  }
433 
434  if (mProjectAttrs.havesel0)
435  {
436  viewInfo.selectedRegion.setT0(mProjectAttrs.sel0);
437  }
438 
439  if (mProjectAttrs.havesel1)
440  {
441  viewInfo.selectedRegion.setT1(mProjectAttrs.sel1);
442  }
443 
444 #ifdef EXPERIMENTAL_SPECTRAL_EDITING
445  if (mProjectAttrs.haveselLow)
446  {
447  viewInfo.selectedRegion.setF0(mProjectAttrs.selLow);
448  }
449 
450  if (mProjectAttrs.haveselHigh)
451  {
452  viewInfo.selectedRegion.setF1(mProjectAttrs.selHigh);
453  }
454 #endif
455 
456  return mUpdateResult;
457 }
458 
460 {
461  return 1;
462 }
463 
465 {
466  static TranslatableStrings empty;
467  return empty;
468 }
469 
470 void AUPImportFileHandle::SetStreamUsage(wxInt32 WXUNUSED(StreamID), bool WXUNUSED(Use))
471 {
472 }
473 
475 {
476  wxFFile ff(mFilename, wxT("rb"));
477  if (ff.IsOpened())
478  {
479  char buf[256];
480 
481  int numRead = ff.Read(buf, sizeof(buf));
482 
483  ff.Close();
484 
485  buf[sizeof(buf) - 1] = '\0';
486 
487  if (!wxStrncmp(buf, wxT("AudacityProject"), 15))
488  {
490  XO("This project was saved by Audacity version 1.0 or earlier. The format has\n"
491  "changed and this version of Audacity is unable to import the project.\n\n"
492  "Use a version of Audacity prior to v3.0.0 to upgrade the project and then\n"
493  "you may import it with this version of Audacity."),
494  XO("Import Project"),
495  wxOK | wxCENTRE,
497 
498  return false;
499  }
500 
501  if (wxStrncmp(buf, "<?xml", 5) == 0 &&
502  (wxStrstr(buf, "<audacityproject") ||
503  wxStrstr(buf, "<project") ))
504  {
505  return true;
506  }
507  }
508 
509  return false;
510 }
511 
513 {
514  return this;
515 }
516 
518 {
520  {
521  return;
522  }
523 
524  struct node node = mHandlers.back();
525 
526  if (wxStrcmp(tag, wxT("waveclip")) == 0)
527  {
528  mClip = nullptr;
529  }
530 
531  if (node.handler)
532  {
534  }
535 
536  mHandlers.pop_back();
537 
538  if (mHandlers.size())
539  {
540  node = mHandlers.back();
542  mCurrentTag = node.tag;
543  }
544 }
545 
546 bool AUPImportFileHandle::HandleXMLTag(const wxChar *tag, const wxChar **attrs)
547 {
549  {
550  return false;
551  }
552 
554  mCurrentTag = tag;
555  mAttrs = attrs;
556 
557  XMLTagHandler *handler = nullptr;
558  bool success = false;
559 
560  if (mCurrentTag.IsSameAs(wxT("project")) ||
561  mCurrentTag.IsSameAs(wxT("audacityproject")))
562  {
563  success = HandleProject(handler);
564  }
565  else if (mCurrentTag.IsSameAs(wxT("labeltrack")))
566  {
567  success = HandleLabelTrack(handler);
568  }
569  else if (mCurrentTag.IsSameAs(wxT("notetrack")))
570  {
571  success = HandleNoteTrack(handler);
572  }
573  else if (mCurrentTag.IsSameAs(wxT("timetrack")))
574  {
575  success = HandleTimeTrack(handler);
576  }
577  else if (mCurrentTag.IsSameAs(wxT("wavetrack")))
578  {
579  success = HandleWaveTrack(handler);
580  }
581  else if (mCurrentTag.IsSameAs(wxT("tags")))
582  {
583  success = HandleTags(handler);
584  }
585  else if (mCurrentTag.IsSameAs(wxT("tag")))
586  {
587  success = HandleTag(handler);
588  }
589  else if (mCurrentTag.IsSameAs(wxT("label")))
590  {
591  success = HandleLabel(handler);
592  }
593  else if (mCurrentTag.IsSameAs(wxT("waveclip")))
594  {
595  success = HandleWaveClip(handler);
596  }
597  else if (mCurrentTag.IsSameAs(wxT("sequence")))
598  {
599  success = HandleSequence(handler);
600  }
601  else if (mCurrentTag.IsSameAs(wxT("waveblock")))
602  {
603  success = HandleWaveBlock(handler);
604  }
605  else if (mCurrentTag.IsSameAs(wxT("envelope")))
606  {
607  success = HandleEnvelope(handler);
608  }
609  else if (mCurrentTag.IsSameAs(wxT("controlpoint")))
610  {
611  success = HandleControlPoint(handler);
612  }
613  else if (mCurrentTag.IsSameAs(wxT("simpleblockfile")))
614  {
615  success = HandleSimpleBlockFile(handler);
616  }
617  else if (mCurrentTag.IsSameAs(wxT("silentblockfile")))
618  {
619  success = HandleSilentBlockFile(handler);
620  }
621  else if (mCurrentTag.IsSameAs(wxT("pcmaliasblockfile")))
622  {
623  success = HandlePCMAliasBlockFile(handler);
624  }
625  else if (mCurrentTag.IsSameAs(wxT("import")))
626  {
627  success = HandleImport(handler);
628  }
629 
630  if (!success || (handler && !handler->HandleXMLTag(tag, attrs)))
631  {
632  return SetError(XO("Internal error in importer...tag not recognized"));
633  }
634 
635  mHandlers.push_back({mParentTag, mCurrentTag, handler});
636 
637  return true;
638 }
639 
641 {
642  auto &fileMan = ProjectFileManager::Get(mProject);
643  auto &window = GetProjectFrame(mProject);
644 
645  int requiredTags = 0;
646 
647  while (*mAttrs)
648  {
649  const wxChar *attr = *mAttrs++;
650  const wxChar *value = *mAttrs++;
651  double dValue;
652 
653  if (!value)
654  {
655  break;
656  }
657 
658  if (!XMLValueChecker::IsGoodString(value))
659  {
660  return SetError(XO("Invalid project '%s' attribute.").Format(attr));
661  }
662 
663  wxString strValue = value;
664 
665 #define set(f, v) (mProjectAttrs.have ## f = true, mProjectAttrs.f = v)
666 
667  // ViewInfo
668  if (!wxStrcmp(attr, wxT("vpos")))
669  {
670  long lValue;
671  if (!XMLValueChecker::IsGoodInt(strValue) || !strValue.ToLong(&lValue) || (lValue < 0))
672  {
673  return SetError(XO("Invalid project 'vpos' attribute."));
674  }
675 
676  set(vpos, (int) lValue);
677  }
678  else if (!wxStrcmp(attr, wxT("h")))
679  {
680  if (!Internat::CompatibleToDouble(value, &dValue))
681  {
682  return SetError(XO("Invalid project 'h' attribute."));
683  }
684 
685  set(h, dValue);
686  }
687  else if (!wxStrcmp(attr, wxT("zoom")))
688  {
689  if (!Internat::CompatibleToDouble(value, &dValue) || (dValue < 0.0))
690  {
691  return SetError(XO("Invalid project 'zoom' attribute."));
692  }
693 
694  set(zoom, dValue);
695  }
696  // Viewinfo.SelectedRegion
697  else if (!wxStrcmp(attr, wxT("sel0")))
698  {
699  if (!Internat::CompatibleToDouble(value, &dValue) || (dValue < 0.0))
700  {
701  return SetError(XO("Invalid project 'sel0' attribute."));
702  }
703 
704  set(sel0, dValue);
705  }
706  else if (!wxStrcmp(attr, wxT("sel1")))
707  {
708  if (!Internat::CompatibleToDouble(value, &dValue) || (dValue < 0.0))
709  {
710  return SetError(XO("Invalid project 'sel1' attribute."));
711  }
712 
713  set(sel1, dValue);
714  }
715 #ifdef EXPERIMENTAL_SPECTRAL_EDITING
716  else if (!wxStrcmp(attr, wxT("selLow")))
717  {
718  if (!Internat::CompatibleToDouble(value, &dValue) || (dValue < 0.0))
719  {
720  return SetError(XO("Invalid project 'selLow' attribute."));
721  }
722 
723  set(selLow, dValue);
724  }
725  else if (!wxStrcmp(attr, wxT("selHigh")))
726  {
727  if (!Internat::CompatibleToDouble(value, &dValue) || (dValue < 0.0))
728  {
729  return SetError(XO("Invalid project 'selHigh' attribute."));
730  }
731 
732  set(selHigh, dValue);
733  }
734 #endif
735  else if (!wxStrcmp(attr, wxT("version")))
736  {
737  requiredTags++;
738  }
739 
740  else if (!wxStrcmp(attr, wxT("audacityversion")))
741  {
742  requiredTags++;
743  }
744  else if (!wxStrcmp(attr, wxT("projname")))
745  {
746  requiredTags++;
747 
749  wxString altname = mProjDir.GetName() + wxT("_data");
750  mProjDir.SetFullName(wxEmptyString);
751 
752  wxString projName = value;
753  bool found = false;
754 
755  // First try to load the data files based on the _data dir given in the .aup file
756  if (!projName.empty())
757  {
758  mProjDir.AppendDir(projName);
759  if (!mProjDir.DirExists())
760  {
761  mProjDir.RemoveLastDir();
762  projName.clear();
763  }
764  }
765 
766  // If that fails then try to use the filename of the .aup as the base directory
767  // This is because unzipped projects e.g. those that get transferred between mac-pc
768  // may have encoding issues and end up expanding the wrong filenames for certain
769  // international characters (such as capital 'A' with an umlaut.)
770  if (projName.empty())
771  {
772  projName = altname;
773  mProjDir.AppendDir(projName);
774  if (!mProjDir.DirExists())
775  {
776  projName.clear();
777  }
778  }
779 
780  // No luck...complain and bail
781  if (projName.empty())
782  {
784  XO("Couldn't find the project data folder: \"%s\"").Format(value),
785  XO("Error Opening Project"),
786  wxOK | wxCENTRE,
787  &window);
788 
789  return false;
790  }
791 
792  // Collect and hash the file names within the project directory
793  wxArrayString files;
794  size_t cnt = wxDir::GetAllFiles(mProjDir.GetFullPath(),
795  &files,
796  "*.*");
797 
798  for (const auto &fn : files)
799  {
800  mFileMap[wxFileNameFromPath(fn)] = {fn, {}};
801  }
802  }
803  else if (!wxStrcmp(attr, wxT("rate")))
804  {
805  if (!Internat::CompatibleToDouble(value, &dValue) || (dValue < 0.0))
806  {
807  return SetError(XO("Invalid project 'selLow' attribute."));
808  }
809 
810  set(rate, dValue);
811  }
812 
813  else if (!wxStrcmp(attr, wxT("snapto")))
814  {
815  set(snapto, (strValue == wxT("on") ? true : false));
816  }
817 
818  else if (!wxStrcmp(attr, wxT("selectionformat")))
819  {
820  set(selectionformat, strValue);
821  }
822 
823  else if (!wxStrcmp(attr, wxT("audiotimeformat")))
824  {
825  set(audiotimeformat, strValue);
826  }
827 
828  else if (!wxStrcmp(attr, wxT("frequencyformat")))
829  {
830  set(frequencyformat, strValue);
831  }
832 
833  else if (!wxStrcmp(attr, wxT("bandwidthformat")))
834  {
835  set(bandwidthformat, strValue);
836  }
837 #undef set
838  }
839 
840  if (requiredTags < 3)
841  {
842  return false;
843  }
844 
845  // Do not set the handler - already handled
846 
847  return true;
848 }
849 
851 {
852  handler = TrackList::Get(mProject).Add(std::make_shared<LabelTrack>());
853 
854  return true;
855 }
856 
858 {
859 #if defined(USE_MIDI)
860  handler = TrackList::Get(mProject).Add(std::make_shared<NoteTrack>());
861 
862  return true;
863 #else
865  XO("MIDI tracks found in project file, but this build of Audacity does not include MIDI support, bypassing track."),
866  XO("Project Import"),
867  wxOK | wxICON_EXCLAMATION | wxCENTRE,
869 
870  return false;
871 #endif
872 }
873 
875 {
876  auto &tracks = TrackList::Get(mProject);
877 
878  // Bypass this timetrack if the project already has one
879  // (See HandleTimeEnvelope and HandleControlPoint also)
880  if (*tracks.Any<TimeTrack>().begin())
881  {
883  XO("The active project already has a time track and one was encountered in the project being imported, bypassing imported time track."),
884  XO("Project Import"),
885  wxOK | wxICON_EXCLAMATION | wxCENTRE,
887 
888  return true;
889  }
890 
891  auto &viewInfo = ViewInfo::Get( mProject );
892  handler =
893  TrackList::Get(mProject).Add(std::make_shared<TimeTrack>(&viewInfo));
894 
895  return true;
896 }
897 
899 {
900  auto &trackFactory = WaveTrackFactory::Get(mProject);
901  handler = mWaveTrack =
902  TrackList::Get(mProject).Add(trackFactory.NewWaveTrack());
903 
904  // No active clip. In early versions of Audacity, there was a single
905  // implied clip so we'll create a clip when the first "sequence" is
906  // found.
907  mClip = nullptr;
908 
909  return true;
910 }
911 
913 {
914  wxString n;
915  wxString v;
916 
917  // Support for legacy tags
918  while(*mAttrs)
919  {
920  const wxChar *attr = *mAttrs++;
921  const wxChar *value = *mAttrs++;
922 
923  if (!value)
924  {
925  break;
926  }
927 
928  // Ignore empty tags
929  if (!*value)
930  {
931  continue;
932  }
933 
935  {
936  // Log it???
937  return false;
938  }
939 
940  if (!wxStrcmp(attr, "id3v2"))
941  {
942  continue;
943  }
944  else if (!wxStrcmp(attr, "track"))
945  {
946  n = wxT("TRACKNUMBER");
947  }
948  else
949  {
950  n = attr;
951  n.MakeUpper();
952  }
953 
954  mTags->SetTag(n, value);
955  }
956 
957  // Do not set the handler - already handled
958 
959  return true;
960 }
961 
963 {
964  if (!mParentTag.IsSameAs(wxT("tags")))
965  {
966  return false;
967  }
968 
969  wxString n, v;
970 
971  while (*mAttrs)
972  {
973  wxString attr = *mAttrs++;
974  if (attr.empty())
975  {
976  break;
977  }
978  wxString value = *mAttrs++;
979 
981  {
982  break;
983  }
984 
985  if (attr == wxT("name"))
986  {
987  n = value;
988  }
989  else if (attr == wxT("value"))
990  {
991  v = value;
992  }
993  }
994 
995  if (n == wxT("id3v2"))
996  {
997  // LLL: This is obsolete, but it must be handled and ignored.
998  }
999  else
1000  {
1001  mTags->SetTag(n, v);
1002  }
1003 
1004  // Do not set the handler - already handled
1005 
1006  return true;
1007 }
1008 
1010 {
1011  if (!mParentTag.IsSameAs(wxT("labeltrack")))
1012  {
1013  return false;
1014  }
1015 
1016  // The parent handler also handles this tag
1017  handler = mHandlers.back().handler;
1018 
1019  return true;
1020 }
1021 
1023 {
1024  struct node node = mHandlers.back();
1025 
1026  if (mParentTag.IsSameAs(wxT("wavetrack")))
1027  {
1028  WaveTrack *wavetrack = static_cast<WaveTrack *>(node.handler);
1029 
1030  handler = wavetrack->CreateClip();
1031  }
1032  else if (mParentTag.IsSameAs(wxT("waveclip")))
1033  {
1034  // Nested wave clips are cut lines
1035  WaveClip *waveclip = static_cast<WaveClip *>(node.handler);
1036 
1037  handler = waveclip->HandleXMLChild(mCurrentTag);
1038  }
1039 
1040  mClip = static_cast<WaveClip *>(handler);
1041  mClips.push_back(mClip);
1042 
1043  return true;
1044 }
1045 
1047 {
1048  struct node node = mHandlers.back();
1049 
1050  if (mParentTag.IsSameAs(wxT("timetrack")))
1051  {
1052  // If an imported timetrack was bypassed, then we want to bypass the
1053  // envelope as well. (See HandleTimeTrack and HandleControlPoint)
1054  if (node.handler)
1055  {
1056  TimeTrack *timetrack = static_cast<TimeTrack *>(node.handler);
1057 
1058  handler = timetrack->GetEnvelope();
1059  }
1060  }
1061  // Earlier versions of Audacity had a single implied waveclip, so for
1062  // these versions, we get or create the only clip in the track.
1063  else if (mParentTag.IsSameAs(wxT("wavetrack")))
1064  {
1065  handler = mWaveTrack->RightmostOrNewClip()->GetEnvelope();
1066  }
1067  // Nested wave clips are cut lines
1068  else if (mParentTag.IsSameAs(wxT("waveclip")))
1069  {
1070  WaveClip *waveclip = static_cast<WaveClip *>(node.handler);
1071 
1072  handler = waveclip->GetEnvelope();
1073  }
1074 
1075  return true;
1076 }
1077 
1079 {
1080  struct node node = mHandlers.back();
1081 
1082  if (mParentTag.IsSameAs(wxT("envelope")))
1083  {
1084  // If an imported timetrack was bypassed, then we want to bypass the
1085  // control points as well. (See HandleTimeTrack and HandleEnvelope)
1086  if (node.handler)
1087  {
1088  Envelope *envelope = static_cast<Envelope *>(node.handler);
1089 
1090  handler = envelope->HandleXMLChild(mCurrentTag);
1091  }
1092  }
1093 
1094  return true;
1095 }
1096 
1098 {
1099  struct node node = mHandlers.back();
1100 
1101  WaveClip *waveclip = static_cast<WaveClip *>(node.handler);
1102 
1103  // Earlier versions of Audacity had a single implied waveclip, so for
1104  // these versions, we get or create the only clip in the track.
1105  if (mParentTag.IsSameAs(wxT("wavetrack")))
1106  {
1107  XMLTagHandler *dummy;
1108  HandleWaveClip(dummy);
1109  waveclip = mClip;
1110  }
1111 
1112  while(*mAttrs)
1113  {
1114  const wxChar *attr = *mAttrs++;
1115  const wxChar *value = *mAttrs++;
1116 
1117  if (!value)
1118  {
1119  break;
1120  }
1121 
1122  const wxString strValue = value; // promote string, we need this for all
1123 
1124  if (!wxStrcmp(attr, wxT("maxsamples")))
1125  {
1126  // This attribute is a sample count, so can be 64bit
1127  long long llvalue;
1128  if (!XMLValueChecker::IsGoodInt64(strValue) || !strValue.ToLongLong(&llvalue) || (llvalue < 0))
1129  {
1130  return SetError(XO("Invalid sequence 'maxsamples' attribute."));
1131  }
1132 
1133  // Dominic, 12/10/2006:
1134  // Let's check that maxsamples is >= 1024 and <= 64 * 1024 * 1024
1135  // - that's a pretty wide range of reasonable values.
1136  if ((llvalue < 1024) || (llvalue > 64 * 1024 * 1024))
1137  {
1138  return SetError(XO("Invalid sequence 'maxsamples' attribute."));
1139  }
1140  }
1141  else if (!wxStrcmp(attr, wxT("sampleformat")))
1142  {
1143  // This attribute is a sample format, normal int
1144  long fValue;
1145  if (!XMLValueChecker::IsGoodInt(strValue) || !strValue.ToLong(&fValue) || (fValue < 0) || !XMLValueChecker::IsValidSampleFormat(fValue))
1146  {
1147  return SetError(XO("Invalid sequence 'sampleformat' attribute."));
1148  }
1149 
1150  mFormat = (sampleFormat) fValue;
1151  waveclip->GetSequence()->ConvertToSampleFormat( mFormat );
1152  }
1153  else if (!wxStrcmp(attr, wxT("numsamples")))
1154  {
1155  // This attribute is a sample count, so can be 64bit
1156  long long llvalue;
1157  if (!XMLValueChecker::IsGoodInt64(strValue) || !strValue.ToLongLong(&llvalue) || (llvalue < 0))
1158  {
1159  return SetError(XO("Invalid sequence 'numsamples' attribute."));
1160  }
1161  }
1162  }
1163 
1164  // Do not set the handler - already handled
1165 
1166  return true;
1167 }
1168 
1170 {
1171  while(*mAttrs)
1172  {
1173  const wxChar *attr = *mAttrs++;
1174  const wxChar *value = *mAttrs++;
1175 
1176  if (!value)
1177  {
1178  break;
1179  }
1180 
1181  const wxString strValue = value;
1182 
1183  if (!wxStrcmp(attr, wxT("start")))
1184  {
1185  // making sure that values > 2^31 are OK because long clips will need them.
1186  long long llvalue;
1187  if (!XMLValueChecker::IsGoodInt64(strValue) || !strValue.ToLongLong(&llvalue) || (llvalue < 0))
1188  {
1189  return SetError(XO("Unable to parse the waveblock 'start' attribute"));
1190  }
1191  }
1192  }
1193 
1194  // Do not set the handler - already handled
1195 
1196  return true;
1197 }
1198 
1200 {
1201  FilePath filename;
1202  size_t len = 0;
1203 
1204  while (*mAttrs)
1205  {
1206  const wxChar *attr = *mAttrs++;
1207  const wxChar *value = *mAttrs++;
1208 
1209  if (!value)
1210  {
1211  break;
1212  }
1213 
1214  const wxString strValue = value;
1215 
1216  // Can't use XMLValueChecker::IsGoodFileName here, but do part of its test.
1217  if (!wxStricmp(attr, wxT("filename")))
1218  {
1219  if (XMLValueChecker::IsGoodFileString(strValue))
1220  {
1221  if (mFileMap.find(strValue) != mFileMap.end())
1222  {
1223  filename = mFileMap[strValue].first;
1224  }
1225  else
1226  {
1227  SetWarning(XO("Missing project file %s\n\nInserting silence instead.")
1228  .Format(strValue));
1229  }
1230  }
1231  }
1232  else if (!wxStrcmp(attr, wxT("len")))
1233  {
1234  long lValue;
1235  if (!XMLValueChecker::IsGoodInt(strValue) || !strValue.ToLong(&lValue) || (lValue <= 0))
1236  {
1237  return SetError(XO("Missing or invalid simpleblockfile 'len' attribute."));
1238  }
1239 
1240  len = lValue;
1241  }
1242  }
1243 
1244  // Do not set the handler - already handled
1245 
1246  AddFile(len, mFormat, filename, filename);
1247 
1248  return true;
1249 }
1250 
1252 {
1253  FilePath filename;
1254  size_t len = 0;
1255 
1256  while (*mAttrs)
1257  {
1258  const wxChar *attr = *mAttrs++;
1259  const wxChar *value = *mAttrs++;
1260 
1261  if (!value)
1262  {
1263  break;
1264  }
1265 
1266  const wxString strValue = value;
1267 
1268  if (!wxStrcmp(attr, wxT("len")))
1269  {
1270  long lValue;
1271  if (!XMLValueChecker::IsGoodInt(value) || !strValue.ToLong(&lValue) || !(lValue > 0))
1272  {
1273  return SetError(XO("Missing or invalid silentblockfile 'len' attribute."));
1274  }
1275 
1276  len = lValue;
1277  }
1278  }
1279 
1280  // Do not set the handler - already handled
1281 
1282  AddFile(len, mFormat);
1283 
1284  return true;
1285 }
1286 
1288 {
1289  wxString summaryFilename;
1290  wxFileName filename;
1291  sampleCount start = 0;
1292  size_t len = 0;
1293  int channel = 0;
1294  wxString name;
1295 
1296  while (*mAttrs)
1297  {
1298  const wxChar *attr = *mAttrs++;
1299  const wxChar *value = *mAttrs++;
1300 
1301  if (!value)
1302  {
1303  break;
1304  }
1305 
1306  const wxString strValue = value;
1307 
1308  if (!wxStricmp(attr, wxT("aliasfile")))
1309  {
1310  if (XMLValueChecker::IsGoodPathName(strValue))
1311  {
1312  filename.Assign(strValue);
1313  }
1314  else if (XMLValueChecker::IsGoodFileName(strValue, mProjDir.GetPath()))
1315  {
1316  // Allow fallback of looking for the file name, located in the data directory.
1317  filename.Assign(mProjDir.GetPath(), strValue);
1318  }
1319  else if (XMLValueChecker::IsGoodPathString(strValue))
1320  {
1321  // If the aliased file is missing, we failed XMLValueChecker::IsGoodPathName()
1322  // and XMLValueChecker::IsGoodFileName, because both do existence tests.
1323  SetWarning(XO("Missing alias file %s\n\nInserting silence instead.")
1324  .Format(strValue));
1325  }
1326  }
1327  else if (!wxStricmp(attr, wxT("summaryfile")))
1328  {
1329  summaryFilename = strValue;
1330  }
1331  else if (!wxStricmp(attr, wxT("aliasstart")))
1332  {
1333  long long llValue;
1334  if (!XMLValueChecker::IsGoodInt64(strValue) || !strValue.ToLongLong(&llValue) || (llValue < 0))
1335  {
1336  return SetError(XO("Missing or invalid pcmaliasblockfile 'aliasstart' attribute."));
1337  }
1338 
1339  start = llValue;
1340  }
1341  else if (!wxStricmp(attr, wxT("aliaslen")))
1342  {
1343  long lValue;
1344  if (!XMLValueChecker::IsGoodInt(strValue) || !strValue.ToLong(&lValue) || (lValue <= 0))
1345  {
1346  return SetError(XO("Missing or invalid pcmaliasblockfile 'aliaslen' attribute."));
1347  }
1348 
1349  len = lValue;
1350  }
1351  else if (!wxStricmp(attr, wxT("aliaschannel")))
1352  {
1353  long lValue;
1354  if (!XMLValueChecker::IsGoodInt(strValue) || !strValue.ToLong(&lValue) || (lValue < 0))
1355  {
1356  return SetError(XO("Missing or invalid pcmaliasblockfile 'aliaslen' attribute."));
1357  }
1358 
1359  channel = lValue;
1360  }
1361  }
1362 
1363  // Do not set the handler - already handled
1364 
1365  if (filename.IsOk())
1366  AddFile(len, mFormat,
1367  summaryFilename, filename.GetFullPath(),
1368  start, channel);
1369  else
1370  AddFile(len, mFormat); // will add silence instead
1371 
1372  return true;
1373 }
1374 
1376 {
1377  // Adapted from ImportXMLTagHandler::HandleXMLTag as in version 2.4.2
1378  if (!mAttrs || !(*mAttrs) || wxStrcmp(*mAttrs++, wxT("filename")))
1379  return false;
1380 
1381  wxString strAttr = *mAttrs;
1382  if (!XMLValueChecker::IsGoodPathName(strAttr))
1383  {
1384  // Maybe strAttr is just a fileName, not the full path. Try the project data directory.
1385  wxFileNameWrapper fileName0{ mFilename };
1386  fileName0.SetExt({});
1387  wxFileNameWrapper fileName{
1388  fileName0.GetFullPath() + wxT("_data"), strAttr };
1389  if (XMLValueChecker::IsGoodFileName(strAttr, fileName.GetPath(wxPATH_GET_VOLUME)))
1390  strAttr = fileName.GetFullPath();
1391  else
1392  {
1393  wxLogWarning(wxT("Could not import file: %s"), strAttr);
1394  return false;
1395  }
1396  }
1397 
1398  auto &tracks = TrackList::Get(mProject);
1399  auto oldNumTracks = tracks.size();
1400  Track *pLast = nullptr;
1401  if (oldNumTracks > 0)
1402  pLast = *tracks.Any().rbegin();
1403 
1404  // Guard this call so that C++ exceptions don't propagate through
1405  // the expat library
1406  GuardedCall(
1407  [&] {
1408  ProjectFileManager::Get( mProject ).Import(strAttr, false); },
1409  [&] (AudacityException*) {}
1410  );
1411 
1412  if (oldNumTracks == tracks.size())
1413  return false;
1414 
1415  // Handle other attributes, now that we have the tracks.
1416  // Apply them to all new wave tracks.
1417  ++mAttrs;
1418  const wxChar** pAttr;
1419  bool bSuccess = true;
1420 
1421  auto range = tracks.Any();
1422  if (pLast) {
1423  range = range.StartingWith(pLast);
1424  ++range.first;
1425  }
1426  for (auto pTrack: range.Filter<WaveTrack>())
1427  {
1428  // Most of the "import" tag attributes are the same as for "wavetrack" tags,
1429  // so apply them via WaveTrack::HandleXMLTag().
1430  bSuccess = pTrack->HandleXMLTag(wxT("wavetrack"), mAttrs);
1431 
1432  // "offset" tag is ignored in WaveTrack::HandleXMLTag except for legacy projects,
1433  // so handle it here.
1434  double dblValue;
1435  pAttr = mAttrs;
1436  while (*pAttr)
1437  {
1438  const wxChar *attr = *pAttr++;
1439  const wxChar *value = *pAttr++;
1440  const wxString strValue = value;
1441  if (!wxStrcmp(attr, wxT("offset")) &&
1442  XMLValueChecker::IsGoodString(strValue) &&
1443  Internat::CompatibleToDouble(strValue, &dblValue))
1444  pTrack->SetOffset(dblValue);
1445  }
1446  }
1447  return bSuccess;
1448 }
1449 
1452  const FilePath &blockFilename /* = wxEmptyString */,
1453  const FilePath &audioFilename /* = wxEmptyString */,
1454  sampleCount origin /* = 0 */,
1455  int channel /* = 0 */)
1456 {
1457  fileinfo fi = {};
1458  fi.track = mWaveTrack;
1459  fi.clip = mClip;
1460  fi.blockFile = blockFilename;
1461  fi.audioFile = audioFilename;
1462  fi.len = len;
1463  fi.format = format,
1464  fi.origin = origin,
1465  fi.channel = channel;
1466 
1467  mFiles.push_back(fi);
1468 
1469  mTotalSamples += len;
1470 }
1471 
1473 {
1474  wxASSERT(mClip || mWaveTrack);
1475 
1476  if (mClip)
1477  {
1479  }
1480  else if (mWaveTrack)
1481  {
1483  }
1484 
1485  return true;
1486 }
1487 
1488 // All errors that occur here will simply insert silence and allow the
1489 // import to continue.
1490 bool AUPImportFileHandle::AddSamples(const FilePath &blockFilename,
1491  const FilePath &audioFilename,
1492  sampleCount len,
1494  sampleCount origin /* = 0 */,
1495  int channel /* = 0 */)
1496 {
1497  auto pClip = mClip ? mClip : mWaveTrack->RightmostOrNewClip();
1498  auto &pBlock = mFileMap[wxFileNameFromPath(blockFilename)].second;
1499  if (pBlock) {
1500  // Replicate the sharing of blocks
1501  pClip->AppendSharedBlock( pBlock );
1502  return true;
1503  }
1504 
1505  // Third party library has its own type alias, check it before
1506  // adding origin + size_t
1507  static_assert(sizeof(sampleCount::type) <= sizeof(sf_count_t),
1508  "Type sf_count_t is too narrow to hold a sampleCount");
1509 
1510  SF_INFO info;
1511  memset(&info, 0, sizeof(info));
1512 
1513  wxFile f; // will be closed when it goes out of scope
1514  SNDFILE *sf = nullptr;
1515  bool success = false;
1516 
1517  auto cleanup = finally([&]
1518  {
1519  // Do this before any throwing might happen
1520  if (sf)
1521  {
1522  SFCall<int>(sf_close, sf);
1523  }
1524 
1525  if (!success)
1526  {
1527  SetWarning(XO("Error while processing %s\n\nInserting silence.").Format(audioFilename));
1528 
1529  // If we are unwinding for an exception, don't do another
1530  // potentially throwing operation
1531  if (!std::uncaught_exception())
1532  // If this does throw, let that propagate, don't guard the call
1533  AddSilence(len);
1534  }
1535  });
1536 
1537  if (!f.Open(audioFilename))
1538  {
1539  SetWarning(XO("Failed to open %s").Format(audioFilename));
1540 
1541  return true;
1542  }
1543 
1544  // Even though there is an sf_open() that takes a filename, use the one that
1545  // takes a file descriptor since wxWidgets can open a file with a Unicode name and
1546  // libsndfile can't (under Windows).
1547  sf = SFCall<SNDFILE*>(sf_open_fd, f.fd(), SFM_READ, &info, FALSE);
1548  if (!sf)
1549  {
1550  SetWarning(XO("Failed to open %s").Format(audioFilename));
1551 
1552  return true;
1553  }
1554 
1555  if (origin > 0)
1556  {
1557  if (SFCall<sf_count_t>(sf_seek, sf, origin.as_long_long(), SEEK_SET) < 0)
1558  {
1559  SetWarning(XO("Failed to seek to position %lld in %s")
1560  .Format(origin.as_long_long(), audioFilename));
1561 
1562  return true;
1563  }
1564  }
1565 
1566  sf_count_t cnt = len.as_size_t();
1567  int channels = info.channels;
1568 
1569  wxASSERT(channels >= 1);
1570  wxASSERT(channel < channels);
1571 
1572  SampleBuffer buffer(cnt, format);
1573  samplePtr bufptr = buffer.ptr();
1574 
1575  size_t framesRead = 0;
1576 
1577  // These cases preserve the logic formerly in BlockFile.cpp,
1578  // which was deleted at commit 98d1468.
1579  if (channels == 1 && format == int16Sample && sf_subtype_is_integer(info.format))
1580  {
1581  // If both the src and dest formats are integer formats,
1582  // read integers directly from the file, conversions not needed
1583  framesRead = SFCall<sf_count_t>(sf_readf_short, sf, (short *) bufptr, cnt);
1584  }
1585  else if (channels == 1 && format == int24Sample && sf_subtype_is_integer(info.format))
1586  {
1587  framesRead = SFCall<sf_count_t>(sf_readf_int, sf, (int *) bufptr, cnt);
1588  if (framesRead != cnt)
1589  {
1590  SetWarning(XO("Unable to read %lld samples from %s")
1591  .Format(cnt, audioFilename));
1592 
1593  return true;
1594  }
1595 
1596  // libsndfile gave us the 3 byte sample in the 3 most
1597  // significant bytes -- we want it in the 3 least
1598  // significant bytes.
1599  int *intPtr = (int *) bufptr;
1600  for (size_t i = 0; i < framesRead; i++)
1601  {
1602  intPtr[i] = intPtr[i] >> 8;
1603  }
1604  }
1605  else if (format == int16Sample && !sf_subtype_more_than_16_bits(info.format))
1606  {
1607  // Special case: if the file is in 16-bit (or less) format,
1608  // and the calling method wants 16-bit data, go ahead and
1609  // read 16-bit data directly. This is a pretty common
1610  // case, as most audio files are 16-bit.
1611  SampleBuffer temp(cnt * channels, int16Sample);
1612  short *tmpptr = (short *) temp.ptr();
1613 
1614  framesRead = SFCall<sf_count_t>(sf_readf_short, sf, tmpptr, cnt);
1615  if (framesRead != cnt)
1616  {
1617  SetWarning(XO("Unable to read %lld samples from %s")
1618  .Format(cnt, audioFilename));
1619 
1620  return true;
1621  }
1622 
1623  for (size_t i = 0; i < framesRead; i++)
1624  {
1625  ((short *)bufptr)[i] = tmpptr[(channels * i) + channel];
1626  }
1627  }
1628  else
1629  {
1630  /*
1631  Therefore none of the three cases above:
1632  !(channels == 1 && format == int16Sample && sf_subtype_is_integer(info.format))
1633  &&
1634  !(channels == 1 && format == int24Sample && sf_subtype_is_integer(info.format))
1635  &&
1636  !(format == int16Sample && !sf_subtype_more_than_16_bits(info.format))
1637 
1638  So format is not 16 bits with wider file format (third conjunct),
1639  but still maybe it is 24 bits with float file format (second conjunct).
1640  */
1641 
1642  // Otherwise, let libsndfile handle the conversion and
1643  // scaling, and pass us normalized data as floats. We can
1644  // then convert to whatever format we want.
1645  SampleBuffer tmpbuf(cnt * channels, floatSample);
1646  float *tmpptr = (float *) tmpbuf.ptr();
1647 
1648  framesRead = SFCall<sf_count_t>(sf_readf_float, sf, tmpptr, cnt);
1649  if (framesRead != cnt)
1650  {
1651  SetWarning(XO("Unable to read %lld samples from %s")
1652  .Format(cnt, audioFilename));
1653 
1654  return true;
1655  }
1656 
1657  /*
1658  Dithering will happen in CopySamples if format is 24 bits.
1659  Should that be done?
1660 
1661  Either the file is an ordinary simple block file -- and presumably the
1662  track was saved specifying a matching format, so format is float and
1663  there is no dithering.
1664 
1665  Or else this is the very unusual case of an .auf file, importing PCM data
1666  on demand. The destination format is narrower, requiring dither, only
1667  if the user also specified a narrow format for the track. In such a
1668  case, dithering is right.
1669  */
1670  CopySamples((samplePtr)(tmpptr + channel),
1671  floatSample,
1672  bufptr,
1673  format,
1674  framesRead,
1675  gHighQualityDither /* high quality by default */,
1676  channels /* source stride */);
1677  }
1678 
1679  wxASSERT(mClip || mWaveTrack);
1680 
1681  // Add the samples to the clip/track
1682  if (pClip)
1683  {
1684  pBlock = pClip->AppendNewBlock(bufptr, format, cnt);
1685  }
1686 
1687  // Let the finally block know everything is good
1688  success = true;
1689 
1690  return true;
1691 }
1692 
1694 {
1695  wxLogError(msg.Debug());
1696 
1698  {
1699  mErrorMsg = msg;
1700  }
1701 
1702  // The only place where mUpdateResult is set during XML handling callbacks
1703  mUpdateResult = ProgressResult::Failed;
1704 
1705  return false;
1706 }
1707 
1709 {
1710  wxLogWarning(msg.Debug());
1711 
1712  if (mErrorMsg.empty())
1713  {
1714  mErrorMsg = msg;
1715  }
1716 
1717  return false;
1718 }
SelectionBar::Get
static SelectionBar & Get(AudacityProject &project)
Definition: SelectionBar.cpp:137
AUPImportFileHandle::HandleWaveTrack
bool HandleWaveTrack(XMLTagHandler *&handle)
Definition: ImportAUP.cpp:898
AUPImportFileHandle::HandleWaveClip
bool HandleWaveClip(XMLTagHandler *&handle)
Definition: ImportAUP.cpp:1022
FilePath
wxString FilePath
Definition: Identifier.h:227
TranslatableString
Holds a msgid for the translation catalog; may also bind format arguments.
Definition: TranslatableString.h:32
ViewInfo::Get
static ViewInfo & Get(AudacityProject &project)
Definition: ViewInfo.cpp:156
XMLValueChecker::IsValidSampleFormat
static bool IsValidSampleFormat(const int nValue)
Definition: XMLTagHandler.cpp:184
field
#define field(n, t)
Definition: ImportAUP.cpp:166
AUPImportPlugin::GetPluginFormatDescription
TranslatableString GetPluginFormatDescription() override
Definition: ImportAUP.cpp:240
AUPImportFileHandle::mUpdateResult
ProgressResult mUpdateResult
Definition: ImportAUP.cpp:218
AUPImportFileHandle::HandleTimeTrack
bool HandleTimeTrack(XMLTagHandler *&handle)
Definition: ImportAUP.cpp:874
TranslatableString::empty
bool empty() const
Definition: TranslatableString.h:72
AUPImportFileHandle::HandleSequence
bool HandleSequence(XMLTagHandler *&handle)
Definition: ImportAUP.cpp:1097
AUPImportPlugin::GetPluginStringID
wxString GetPluginStringID() override
Definition: ImportAUP.cpp:235
SNAP_OFF
@ SNAP_OFF
Definition: ProjectSettings.h:29
WaveTrackFactory::Get
static WaveTrackFactory & Get(AudacityProject &project)
Definition: WaveTrack.cpp:2799
WaveTrack
A Track that contains audio waveform data.
Definition: WaveTrack.h:69
GuardedCall
R GuardedCall(const F1 &body, const F2 &handler=F2::Default(), std::function< void(AudacityException *)> delayedHandler=DefaultDelayedHandlerAction{})
Execute some code on any thread; catch any AudacityException; enqueue error report on the main thread...
Definition: AudacityException.h:202
AUPImportFileHandle::HandleLabelTrack
bool HandleLabelTrack(XMLTagHandler *&handle)
Definition: ImportAUP.cpp:850
AUPImportFileHandle::~AUPImportFileHandle
~AUPImportFileHandle()
Definition: ImportAUP.cpp:271
AudacityMessageBox
int AudacityMessageBox(const TranslatableString &message, const TranslatableString &caption=XO("Message"), long style=wxOK|wxCENTRE, wxWindow *parent=NULL, int x=wxDefaultCoord, int y=wxDefaultCoord)
Definition: AudacityMessageBox.h:20
AUPImportFileHandle::HandleNoteTrack
bool HandleNoteTrack(XMLTagHandler *&handle)
Definition: ImportAUP.cpp:857
TrackHolders
std::vector< std::vector< std::shared_ptr< WaveTrack > > > TrackHolders
Definition: Import.h:39
BasicUI::ProgressResult::Success
@ Success
AUPImportFileHandle::mFormat
sampleFormat mFormat
Definition: ImportAUP.cpp:201
DESC
#define DESC
Definition: ImportAUP.cpp:54
fn
static const auto fn
Definition: WaveformView.cpp:1114
wxFileNameWrapper
Definition: wxFileNameWrapper.h:21
XMLValueChecker::IsGoodInt
static bool IsGoodInt(const wxString &strInt)
Check that the supplied string can be converted to a long (32bit) integer.
Definition: XMLTagHandler.cpp:160
TranslatableStrings
std::vector< TranslatableString > TranslatableStrings
Definition: TranslatableString.h:295
Sequence::ConvertToSampleFormat
bool ConvertToSampleFormat(sampleFormat format, const std::function< void(size_t)> &progressReport={})
Definition: Sequence.cpp:136
AUPImportFileHandle::mAttrs
const wxChar ** mAttrs
Definition: ImportAUP.cpp:207
WaveClip::GetEnvelope
Envelope * GetEnvelope()
Definition: WaveClip.h:243
WaveTrack::GetEndTime
double GetEndTime() const override
Get the time at which the last clip in the track ends, plus recorded stuff.
Definition: WaveTrack.cpp:1800
ImportPlugin
Base class for FlacImportPlugin, LOFImportPlugin, MP3ImportPlugin, OggImportPlugin and PCMImportPlugi...
Definition: ImportPlugin.h:67
XMLValueChecker::IsGoodPathName
static bool IsGoodPathName(const FilePath &strPathName)
Definition: XMLTagHandler.cpp:101
Import.h
Tags
ID3 Tags (for MP3)
Definition: Tags.h:74
WaveClip::HandleXMLChild
XMLTagHandler * HandleXMLChild(const wxChar *tag) override
Definition: WaveClip.cpp:1334
AUPImportFileHandle::HandlePCMAliasBlockFile
bool HandlePCMAliasBlockFile(XMLTagHandler *&handle)
Definition: ImportAUP.cpp:1287
AUPImportFileHandle::mProjDir
wxFileName mProjDir
Definition: ImportAUP.cpp:209
Format
Abstract base class used in importing a file.
BasicUI::ProgressResult
ProgressResult
Definition: BasicUI.h:145
WaveTrack::RightmostOrNewClip
WaveClip * RightmostOrNewClip()
Get access to the last (rightmost) clip, or create a clip, if there is not already one.
Definition: WaveTrack.cpp:2162
Envelope
Piecewise linear or piecewise exponential function from double to double.
Definition: Envelope.h:71
XMLTagHandler::HandleXMLEndTag
virtual void HandleXMLEndTag(const wxChar *WXUNUSED(tag))
Definition: XMLTagHandler.h:97
WaveClip::GetEndTime
double GetEndTime() const
Definition: WaveClip.cpp:253
AUPImportFileHandle::AddSamples
bool AddSamples(const FilePath &blockFilename, const FilePath &audioFilename, sampleCount len, sampleFormat format, sampleCount origin=0, int channel=0)
Definition: ImportAUP.cpp:1490
XMLValueChecker::IsGoodInt64
static bool IsGoodInt64(const wxString &strInt)
Check that the supplied string can be converted to a 64bit integer.
Definition: XMLTagHandler.cpp:166
XO
#define XO(s)
Definition: Internat.h:31
AUPImportFileHandle::mParentTag
wxString mParentTag
Definition: ImportAUP.cpp:205
ProjectSettings::Get
static ProjectSettings & Get(AudacityProject &project)
Definition: ProjectSettings.cpp:40
TrackList::Add
TrackKind * Add(const std::shared_ptr< TrackKind > &t)
Definition: Track.h:1487
int24Sample
@ int24Sample
Definition: SampleFormat.h:33
AUPImportFileHandle::AddFile
void AddFile(sampleCount len, sampleFormat format, const FilePath &blockFilename=wxEmptyString, const FilePath &audioFilename=wxEmptyString, sampleCount origin=0, int channel=0)
Definition: ImportAUP.cpp:1450
Track::Any
bool Any() const
Definition: Track.cpp:361
AUPImportFileHandle::mClip
WaveClip * mClip
Definition: ImportAUP.cpp:215
TranslatableString::Debug
wxString Debug() const
Format as an English string for debugging logs and developers' eyes, not for end users.
Definition: TranslatableString.h:82
SelectedRegion::UndefinedFrequency
static const int UndefinedFrequency
Definition: SelectedRegion.h:44
AUPImportFileHandle::node
Definition: ImportAUP.cpp:111
registered
static Importer::RegisteredImportPlugin registered
Definition: ImportAUP.cpp:260
AUPImportFileHandle::HandleXMLChild
XMLTagHandler * HandleXMLChild(const wxChar *tag) override
Definition: ImportAUP.cpp:512
AUPImportFileHandle::HandleXMLTag
bool HandleXMLTag(const wxChar *tag, const wxChar **attrs) override
Definition: ImportAUP.cpp:546
AUPImportFileHandle::HandleProject
bool HandleProject(XMLTagHandler *&handle)
Definition: ImportAUP.cpp:640
set
#define set(f, v)
AUPImportFileHandle::fileinfo::origin
sampleCount origin
Definition: ImportAUP.cpp:195
AUPImportFileHandle
An ImportFileHandle for AUP files (pre-AUP3)
Definition: ImportAUP.cpp:87
ImportFileHandle::mProgress
std::unique_ptr< ProgressDialog > mProgress
Definition: ImportPlugin.h:159
wxArrayStringEx
Extend wxArrayString with move operations and construction and insertion fromstd::initializer_list.
Definition: wxArrayStringEx.h:18
AUPImportFileHandle::HandleImport
bool HandleImport(XMLTagHandler *&handle)
Definition: ImportAUP.cpp:1375
XMLValueChecker::IsGoodString
static bool IsGoodString(const wxString &str)
Definition: XMLTagHandler.cpp:41
AUPImportFileHandle::mClips
std::vector< WaveClip * > mClips
Definition: ImportAUP.cpp:216
AUPImportFileHandle::mHandlers
stack mHandlers
Definition: ImportAUP.cpp:204
Envelope::HandleXMLChild
XMLTagHandler * HandleXMLChild(const wxChar *tag) override
Definition: Envelope.cpp:332
XMLFileReader::Parse
bool Parse(XMLTagHandler *baseHandler, const FilePath &fname)
Definition: XMLFileReader.cpp:42
WaveClip::GetSequence
Sequence * GetSequence()
Definition: WaveClip.h:251
floatSample
@ floatSample
Definition: SampleFormat.h:34
AUPImportFileHandle::HandleSimpleBlockFile
bool HandleSimpleBlockFile(XMLTagHandler *&handle)
Definition: ImportAUP.cpp:1199
AUPImportFileHandle::fileinfo::clip
WaveClip * clip
Definition: ImportAUP.cpp:190
WaveClip
This allows multiple clips to be a part of one WaveTrack.
Definition: WaveClip.h:173
SNAP_NEAREST
@ SNAP_NEAREST
Definition: ProjectSettings.h:30
AUPImportFileHandle::GetStreamCount
wxInt32 GetStreamCount() override
Definition: ImportAUP.cpp:459
NumericConverter::LookupFormat
static NumericFormatSymbol LookupFormat(Type type, const wxString &id)
Definition: NumericTextCtrl.cpp:702
AudacityException
Base class for exceptions specially processed by the application.
Definition: AudacityException.h:33
ImportFileHandle::CreateProgress
void CreateProgress()
Definition: ImportPlugin.cpp:45
AUPImportFileHandle::HandleTag
bool HandleTag(XMLTagHandler *&handle)
Definition: ImportAUP.cpp:962
AUPImportFileHandle::AUPImportFileHandle
AUPImportFileHandle(const FilePath &name, AudacityProject *project)
Definition: ImportAUP.cpp:264
WaveTrack::InsertSilence
void InsertSilence(double t, double len) override
Definition: WaveTrack.cpp:1370
XMLFileReader::GetErrorStr
const TranslatableString & GetErrorStr() const
Definition: XMLFileReader.cpp:178
AUPImportFileHandle::GetFileUncompressedBytes
ByteCount GetFileUncompressedBytes() override
Definition: ImportAUP.cpp:280
Tags::SetTag
void SetTag(const wxString &name, const wxString &value, const bool bSpecialTag=false)
Definition: Tags.cpp:486
AUPImportFileHandle::fileinfo::channel
int channel
Definition: ImportAUP.cpp:196
ProjectFileManager::Get
static ProjectFileManager & Get(AudacityProject &project)
Definition: ProjectFileManager.cpp:61
WaveTrack::LongSamplesToTime
double LongSamplesToTime(sampleCount pos) const
Convert correctly between a number of samples and an (absolute) time in seconds.
Definition: WaveTrack.cpp:1775
CopySamples
void CopySamples(constSamplePtr src, sampleFormat srcFormat, samplePtr dst, sampleFormat dstFormat, size_t len, DitherType ditherType, unsigned int srcStride, unsigned int dstStride)
Copy samples from any format to any other format; apply dithering only if narrowing the format.
Definition: SampleFormat.cpp:111
ProjectSelectionManager::Get
static ProjectSelectionManager & Get(AudacityProject &project)
Definition: ProjectSelectionManager.cpp:34
AUPImportFileHandle::mErrorMsg
TranslatableString mErrorMsg
Definition: ImportAUP.cpp:219
sampleCount::as_long_long
long long as_long_long() const
Definition: SampleCount.h:47
int16Sample
@ int16Sample
Definition: SampleFormat.h:32
GetProjectFrame
AUDACITY_DLL_API wxFrame & GetProjectFrame(AudacityProject &project)
Get the top-level window associated with the project (as a wxFrame only, when you do not need to use ...
Definition: Project.cpp:188
AUPImportPlugin::~AUPImportPlugin
~AUPImportPlugin()
Definition: ImportAUP.cpp:231
AUPImportFileHandle::HandleWaveBlock
bool HandleWaveBlock(XMLTagHandler *&handle)
Definition: ImportAUP.cpp:1169
TimeTrack::GetEnvelope
BoundedEnvelope * GetEnvelope()
Definition: TimeTrack.h:77
AUPImportFileHandle::SetStreamUsage
void SetStreamUsage(wxInt32 WXUNUSED(StreamID), bool WXUNUSED(Use)) override
Definition: ImportAUP.cpp:470
name
const TranslatableString name
Definition: Distortion.cpp:98
XMLValueChecker::IsGoodFileName
static bool IsGoodFileName(const FilePath &strFileName, const FilePath &strDirName={})
Definition: XMLTagHandler.cpp:61
NumericConverter::TIME
@ TIME
Definition: NumericTextCtrl.h:52
AUPImportFileHandle::HandleXMLEndTag
void HandleXMLEndTag(const wxChar *tag) override
Definition: ImportAUP.cpp:517
format
int format
Definition: ExportPCM.cpp:56
AUPImportFileHandle::fileinfo::len
sampleCount len
Definition: ImportAUP.cpp:193
AUPImportPlugin
An ImportPlugin for AUP files (pre-AUP3)
Definition: ImportAUP.cpp:72
AUPImportFileHandle::HandleSilentBlockFile
bool HandleSilentBlockFile(XMLTagHandler *&handle)
Definition: ImportAUP.cpp:1251
ImportFileHandle::mFilename
FilePath mFilename
Definition: ImportPlugin.h:158
ImportHandle
std::unique_ptr< ImportFileHandle > ImportHandle
Definition: ImportAUP.cpp:67
ImportFileHandle
An ImportFileHandle for data.
Definition: ImportPlugin.h:107
sampleCount::type
long long type
Definition: SampleCount.h:20
AUPImportFileHandle::mProjectAttrs
struct AUPImportFileHandle::@0 mProjectAttrs
XMLValueChecker::IsGoodFileString
static bool IsGoodFileString(const FilePath &str)
Definition: XMLTagHandler.cpp:73
AUPImportFileHandle::mTotalSamples
sampleCount mTotalSamples
Definition: ImportAUP.cpp:199
sampleCount::as_size_t
size_t as_size_t() const
Definition: SampleCount.cpp:15
AUPImportFileHandle::node::handler
XMLTagHandler * handler
Definition: ImportAUP.cpp:114
AUPImportFileHandle::HandleControlPoint
bool HandleControlPoint(XMLTagHandler *&handle)
Definition: ImportAUP.cpp:1078
WaveTrackFactory
Used to create or clone a WaveTrack, with appropriate context from the project that will own the trac...
Definition: WaveTrack.h:701
AUPImportPlugin::Open
ImportHandle Open(const FilePath &fileName, AudacityProject *project) override
Definition: ImportAUP.cpp:245
XMLTagHandler
This class is an interface which should be implemented by classes which wish to be able to load and s...
Definition: XMLTagHandler.h:80
SampleBuffer
Definition: SampleFormat.h:69
sampleFormat
sampleFormat
Definition: SampleFormat.h:29
samplePtr
char * samplePtr
Definition: SampleFormat.h:49
AUPImportFileHandle::fileinfo::format
sampleFormat format
Definition: ImportAUP.cpp:194
sf_subtype_more_than_16_bits
bool sf_subtype_more_than_16_bits(unsigned int format)
Definition: FileFormats.cpp:190
AUPImportFileHandle::GetFileDescription
TranslatableString GetFileDescription() override
Definition: ImportAUP.cpp:275
TrackList::Get
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:495
XMLFileReader
Reads a file and passes the results through an XMLTagHandler.
Definition: XMLFileReader.h:20
AUPImportFileHandle::node::tag
wxString tag
Definition: ImportAUP.cpp:113
Track
Abstract base class for an object holding data associated with points on a time axis.
Definition: Track.h:239
sampleCount
Positions or offsets within audio files need a wide type.
Definition: SampleCount.h:18
AudacityProject
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:113
ImportPlugin.h
The interface that all file import "plugins" (if you want to call them that) must implement....
AUPImportFileHandle::stack
std::vector< struct node > stack
Definition: ImportAUP.cpp:116
Importer::RegisteredImportPlugin
Definition: Import.h:85
AUPImportFileHandle::mNumChannels
unsigned long mNumChannels
Definition: ImportAUP.cpp:202
AUPImportFileHandle::node::parent
wxString parent
Definition: ImportAUP.cpp:112
AUPImportFileHandle::fileinfo
Definition: ImportAUP.cpp:188
AUPImportFileHandle::HandleTags
bool HandleTags(XMLTagHandler *&handle)
Definition: ImportAUP.cpp:912
AUPImportPlugin::AUPImportPlugin
AUPImportPlugin()
Definition: ImportAUP.cpp:222
XMLTagHandler::HandleXMLTag
virtual bool HandleXMLTag(const wxChar *tag, const wxChar **attrs)=0
ProjectFileManager::Import
bool Import(const FilePath &fileName, bool addToHistory=true)
Definition: ProjectFileManager.cpp:1197
AUPImportFileHandle::fileinfo::audioFile
FilePath audioFile
Definition: ImportAUP.cpp:192
XMLValueChecker::IsGoodPathString
static bool IsGoodPathString(const FilePath &str)
Definition: XMLTagHandler.cpp:108
gHighQualityDither
DitherType gHighQualityDither
Definition: SampleFormat.cpp:50
AUPImportFileHandle::BlockFileMap
std::map< wxString, std::pair< FilePath, std::shared_ptr< SampleBlock > >> BlockFileMap
Definition: ImportAUP.cpp:211
Prefs.h
AUPImportFileHandle::mCurrentTag
wxString mCurrentTag
Definition: ImportAUP.cpp:206
WaveClip::InsertSilence
void InsertSilence(double t, double len, double *pEnvelopeValue=nullptr)
Definition: WaveClip.cpp:1426
AUPImportFileHandle::fileinfo::track
WaveTrack * track
Definition: ImportAUP.cpp:189
sf_subtype_is_integer
bool sf_subtype_is_integer(unsigned int format)
Definition: FileFormats.cpp:199
NewChannelGroup
std::vector< std::shared_ptr< WaveTrack > > NewChannelGroup
Definition: Import.cpp:62
AUPImportFileHandle::mTags
Tags * mTags
Definition: ImportAUP.cpp:162
AUPImportFileHandle::SetError
bool SetError(const TranslatableString &msg)
Definition: ImportAUP.cpp:1693
ImportFileHandle::ByteCount
unsigned long long ByteCount
Definition: ImportPlugin.h:127
AUPImportFileHandle::mWaveTrack
WaveTrack * mWaveTrack
Definition: ImportAUP.cpp:214
settings
static Settings & settings()
Definition: TrackInfo.cpp:86
AUPImportFileHandle::mFileMap
BlockFileMap mFileMap
Definition: ImportAUP.cpp:212
AUPImportFileHandle::GetStreamInfo
const TranslatableStrings & GetStreamInfo() override
Definition: ImportAUP.cpp:464
AUPImportFileHandle::Import
ProgressResult Import(WaveTrackFactory *trackFactory, TrackHolders &outTracks, Tags *tags) override
Definition: ImportAUP.cpp:286
WaveTrack::CreateClip
WaveClip * CreateClip(double offset=.0)
Definition: WaveTrack.cpp:2144
AUPImportFileHandle::AddSilence
bool AddSilence(sampleCount len)
Definition: ImportAUP.cpp:1472
AUPImportFileHandle::mProject
AudacityProject & mProject
Definition: ImportAUP.cpp:161
AUPImportFileHandle::mFiles
std::vector< fileinfo > mFiles
Definition: ImportAUP.cpp:198
AUPImportFileHandle::SetWarning
bool SetWarning(const TranslatableString &msg)
Definition: ImportAUP.cpp:1708
TimeTrack
A kind of Track used to 'warp time'.
Definition: TimeTrack.h:24
exts
static const auto exts
Definition: ImportAUP.cpp:56
ProjectHistory::Get
static ProjectHistory & Get(AudacityProject &project)
Definition: ProjectHistory.cpp:26
AUPImportFileHandle::HandleEnvelope
bool HandleEnvelope(XMLTagHandler *&handle)
Definition: ImportAUP.cpp:1046
Internat::CompatibleToDouble
static bool CompatibleToDouble(const wxString &stringToConvert, double *result)
Convert a string to a number.
Definition: Internat.cpp:134
AUPImportFileHandle::HandleLabel
bool HandleLabel(XMLTagHandler *&handle)
Definition: ImportAUP.cpp:1009
AUPImportFileHandle::Open
bool Open()
Definition: ImportAUP.cpp:474
AUPImportFileHandle::fileinfo::blockFile
FilePath blockFile
Definition: ImportAUP.cpp:191
SampleBuffer::ptr
samplePtr ptr() const
Definition: SampleFormat.h:98