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