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