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"
25
26#include "Envelope.h"
27#include "FileFormats.h"
28#include "LabelTrack.h"
29#if defined(USE_MIDI)
30#include "NoteTrack.h"
31#endif
32#include "Project.h"
33#include "ProjectFileManager.h"
34#include "ProjectHistory.h"
36#include "ProjectRate.h"
37#include "ProjectSnap.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 "XMLFileReader.h"
47#include "wxFileNameWrapper.h"
48#include "ImportUtils.h"
49
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/log.h>
62#include <wx/string.h>
63
65using ImportHandle = std::unique_ptr<ImportFileHandle>;
66
67class AUPImportPlugin final : public ImportPlugin
68{
69public:
72
73 wxString GetPluginStringID() override;
74
76
77 ImportHandle Open(const FilePath &fileName,
78 AudacityProject *project) override;
79};
80
82 public XMLTagHandler
83{
84public:
88
89 TranslatableString GetErrorMessage() const override;
90
92
94
95 void Import(
96 ImportProgressListener& progressListener, WaveTrackFactory* trackFactory,
97 TrackHolders& outTracks, Tags* tags,
98 std::optional<LibFileFormats::AcidizerTags>& outAcidTags) 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
218 bool mHasParseError { false };
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
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
282: ImportFileHandleEx(fileName),
283 mProject(*project)
284{
285}
286
288{
289}
290
292{
293 return DESC;
294}
295
297{
298 return mErrorMsg;
299}
300
302{
303 // TODO: Get Uncompressed byte count.
304 return 0;
305}
306
309 Tags* tags, std::optional<LibFileFormats::AcidizerTags>&)
310{
311 BeginImport();
312
313 mHasParseError = false;
314
315 auto &history = ProjectHistory::Get(mProject);
317 auto &viewInfo = ViewInfo::Get(mProject);
318 auto &formats = ProjectNumericFormats::Get(mProject);
319
320 auto oldNumTracks = tracks.Size();
321 auto cleanup = finally([this, &tracks, oldNumTracks]{
322 if (mHasParseError || IsCancelled()) {
323 // Revoke additions of tracks
324 while (oldNumTracks < tracks.Size())
325 tracks.Remove(**tracks.end().advance(-1));
326 }
327 });
328
329 bool isDirty = history.GetDirty() || !tracks.empty();
330
331 mTotalSamples = 0;
332
333 mTags = tags;
334
335 XMLFileReader xmlFile;
336
337 bool success = xmlFile.Parse(this, GetFilename());
338 if (!success)
339 {
340 mErrorMsg = XO("Couldn't import the project:\n\n%s").Format(xmlFile.GetErrorStr());
342 return;
343 }
344
346 {
348 return;
349 }
350 if(!mErrorMsg.empty())//i.e. warning
351 {
353 mErrorMsg = {};
354 }
355
356 // (If we keep this entire source file at all)
357
358 sampleCount processed = 0;
359 for (auto fi : mFiles)
360 {
361 if(mTotalSamples.as_double() > 0)
362 progressListener.OnImportProgress(processed.as_double() / mTotalSamples.as_double());
363 if(IsCancelled())
364 {
366 return;
367 }
368 else if(IsStopped())
369 {
371 return;
372 }
373 mClip = fi.clip;
374 mWaveTrack = fi.track;
375
376 if (fi.blockFile.empty())
377 {
378 AddSilence(fi.len);
379 }
380 else
381 {
382 if (!AddSamples(fi.blockFile, fi.audioFile,
383 fi.len, fi.format, fi.origin, fi.channel))
384 {
386 return;
387 }
388 }
389
390 processed += fi.len;
391 }
392
393 for (auto pClip : mClips)
394 pClip->UpdateEnvelopeTrackLen();
395
397 tracks,
398 [&](const auto& errorMessage) { SetError(errorMessage); },
399 [&](const auto& unlinkReason) { SetWarning(XO(
400//i18n-hint: Text of the message dialog that may appear on attempt
401//to import an AUP project.
402//%s will be replaced with an explanation of the actual reason of
403//project modification.
404"%s\n"
405"This feature is not supported in Audacity versions past 3.3.3.\n"
406"These stereo tracks have been split into mono tracks.\n"
407"Please verify that everything works as intended before saving.")
408 .Format(unlinkReason));
409 }
410 );
411
413 {
415 return;
416 }
417 if(!mErrorMsg.empty())
418 {
420 mErrorMsg = {};
421 }
422
423 // If the active project is "dirty", then bypass the below updates as we don't
424 // want to going changing things the user may have already set up.
425 if (isDirty)
426 {
428 return;
429 }
430
431 if (mProjectAttrs.haverate)
433
434 if (mProjectAttrs.havesnapto)
435 {
438 }
439
440 if (mProjectAttrs.haveselectionformat)
441 {
442 formats.SetSelectionFormat(mProjectAttrs.selectionformat);
443 }
444
445 if (mProjectAttrs.haveaudiotimeformat)
446 {
447 formats.SetAudioTimeFormat(mProjectAttrs.audiotimeformat);
448 }
449
450 if (mProjectAttrs.havefrequencyformat)
451 {
452 formats.SetFrequencySelectionFormatName(mProjectAttrs.frequencyformat);
453 }
454
455 if (mProjectAttrs.havebandwidthformat)
456 {
457 formats.SetBandwidthSelectionFormatName(mProjectAttrs.bandwidthformat);
458 }
459
460 // PRL: It seems this must happen after SetSnapTo
461 if (mProjectAttrs.havevpos)
462 {
463 viewInfo.vpos = mProjectAttrs.vpos;
464 }
465
466 if (mProjectAttrs.haveh)
467 {
468 viewInfo.hpos = mProjectAttrs.h;
469 }
470
471 if (mProjectAttrs.havezoom)
472 {
473 viewInfo.SetZoom(mProjectAttrs.zoom);
474 }
475
476 if (mProjectAttrs.havesel0)
477 {
478 viewInfo.selectedRegion.setT0(mProjectAttrs.sel0);
479 }
480
481 if (mProjectAttrs.havesel1)
482 {
483 viewInfo.selectedRegion.setT1(mProjectAttrs.sel1);
484 }
485
486#ifdef EXPERIMENTAL_SPECTRAL_EDITING
487 if (mProjectAttrs.haveselLow)
488 {
489 viewInfo.selectedRegion.setF0(mProjectAttrs.selLow);
490 }
491
492 if (mProjectAttrs.haveselHigh)
493 {
494 viewInfo.selectedRegion.setF1(mProjectAttrs.selHigh);
495 }
496#endif
497
499}
500
502{
503 return 1;
504}
505
507{
508 static TranslatableStrings empty;
509 return empty;
510}
511
512void AUPImportFileHandle::SetStreamUsage(wxInt32 WXUNUSED(StreamID), bool WXUNUSED(Use))
513{
514}
515
517{
518 wxFFile ff(GetFilename(), wxT("rb"));
519 if (ff.IsOpened())
520 {
521 char buf[256];
522
523 int numRead = ff.Read(buf, sizeof(buf));
524
525 ff.Close();
526
527 buf[sizeof(buf) - 1] = '\0';
528
529 if (!wxStrncmp(buf, wxT("AudacityProject"), 15))
530 {
532 XO("This project was saved by Audacity version 1.0 or earlier. The format has\n"
533 "changed and this version of Audacity is unable to import the project.\n\n"
534 "Use a version of Audacity prior to v3.0.0 to upgrade the project and then\n"
535 "you may import it with this version of Audacity."));
536 return false;
537 }
538
539 if (wxStrncmp(buf, "<?xml", 5) == 0 &&
540 (wxStrstr(buf, "<audacityproject") ||
541 wxStrstr(buf, "<project") ))
542 {
543 return true;
544 }
545 }
546
547 return false;
548}
549
551{
552 return this;
553}
554
555void AUPImportFileHandle::HandleXMLEndTag(const std::string_view& tag)
556{
557 if (mHasParseError)
558 {
559 return;
560 }
561
562 struct node node = mHandlers.back();
563
564 if (tag == "waveclip")
565 {
566 mClip = nullptr;
567 }
568
569 if (node.handler)
570 {
572 }
573
574 if (tag == "wavetrack")
576
577 mHandlers.pop_back();
578
579 if (mHandlers.size())
580 {
581 node = mHandlers.back();
584 }
585}
586
587bool AUPImportFileHandle::HandleXMLTag(const std::string_view& tag, const AttributesList &attrs)
588{
589 if (mHasParseError)
590 {
591 return false;
592 }
593
595 mCurrentTag = std::string(tag);
596 mAttrs = attrs;
597
598 XMLTagHandler *handler = nullptr;
599 bool success = false;
600
601 if (mCurrentTag == "project" ||
602 mCurrentTag == "audacityproject")
603 {
604 success = HandleProject(handler);
605 }
606 else if (mCurrentTag == "labeltrack")
607 {
608 success = HandleLabelTrack(handler);
609 }
610 else if (mCurrentTag == "notetrack")
611 {
612 success = HandleNoteTrack(handler);
613 }
614 else if (mCurrentTag == "timetrack")
615 {
616 success = HandleTimeTrack(handler);
617 }
618 else if (mCurrentTag == "wavetrack")
619 {
620 success = HandleWaveTrack(handler);
621 }
622 else if (mCurrentTag == "tags")
623 {
624 success = HandleTags(handler);
625 }
626 else if (mCurrentTag == "tag")
627 {
628 success = HandleTag(handler);
629 }
630 else if (mCurrentTag == "label")
631 {
632 success = HandleLabel(handler);
633 }
634 else if (mCurrentTag == "waveclip")
635 {
636 success = HandleWaveClip(handler);
637 }
638 else if (mCurrentTag == "sequence")
639 {
640 success = HandleSequence(handler);
641 }
642 else if (mCurrentTag == "waveblock")
643 {
644 success = HandleWaveBlock(handler);
645 }
646 else if (mCurrentTag == "envelope")
647 {
648 success = HandleEnvelope(handler);
649 }
650 else if (mCurrentTag == "controlpoint")
651 {
652 success = HandleControlPoint(handler);
653 }
654 else if (mCurrentTag == "simpleblockfile")
655 {
657 }
658 else if (mCurrentTag == "silentblockfile")
659 {
661 }
662 else if (mCurrentTag == "pcmaliasblockfile")
663 {
665 }
666 else if (mCurrentTag == "import")
667 {
668 success = HandleImport(handler);
669 }
670
671 if (!success || (handler && !handler->HandleXMLTag(tag, attrs)))
672 {
673 return SetError(XO("Internal error in importer...tag not recognized"));
674 }
675
677
678 return true;
679}
680
682{
683 auto &fileMan = ProjectFileManager::Get(mProject);
684 auto &window = GetProjectFrame(mProject);
685
686 int requiredTags = 0;
687
688 for (auto pair : mAttrs)
689 {
690 auto attr = pair.first;
691 auto value = pair.second;
692
693 double dValue;
694
695#define set(f, v) (mProjectAttrs.have ## f = true, mProjectAttrs.f = v)
696
697 // ViewInfo
698 if (attr == "vpos")
699 {
700 long lValue;
701 if (!value.TryGet(lValue) || (lValue < 0))
702 {
703 return SetError(XO("Invalid project 'vpos' attribute."));
704 }
705
706 set(vpos, (int) lValue);
707 }
708 else if (attr == "h")
709 {
710 if (!value.TryGet(dValue))
711 {
712 return SetError(XO("Invalid project 'h' attribute."));
713 }
714
715 set(h, dValue);
716 }
717 else if (attr == "zoom")
718 {
719 if (!value.TryGet(dValue) || (dValue < 0.0))
720 {
721 return SetError(XO("Invalid project 'zoom' attribute."));
722 }
723
724 set(zoom, dValue);
725 }
726 // Viewinfo.SelectedRegion
727 else if (attr == "sel0")
728 {
729 if (!value.TryGet(dValue))
730 {
731 return SetError(XO("Invalid project 'sel0' attribute."));
732 }
733
734 set(sel0, dValue);
735 }
736 else if (attr == "sel1")
737 {
738 if (!value.TryGet(dValue))
739 {
740 return SetError(XO("Invalid project 'sel1' attribute."));
741 }
742
743 set(sel1, dValue);
744 }
745#ifdef EXPERIMENTAL_SPECTRAL_EDITING
746 else if (attr == "selLow")
747 {
748 if (!value.TryGet(dValue) || (dValue < 0.0))
749 {
750 return SetError(XO("Invalid project 'selLow' attribute."));
751 }
752
753 set(selLow, dValue);
754 }
755 else if (attr == "selHigh")
756 {
757 if (!value.TryGet(dValue) || (dValue < 0.0))
758 {
759 return SetError(XO("Invalid project 'selHigh' attribute."));
760 }
761
762 set(selHigh, dValue);
763 }
764#endif
765 else if (attr == "version")
766 {
767 requiredTags++;
768 }
769
770 else if (attr == "audacityversion")
771 {
772 requiredTags++;
773 }
774 else if (attr == "projname")
775 {
776 requiredTags++;
777
779 wxString altname = mProjDir.GetName() + wxT("_data");
780 mProjDir.SetFullName(wxEmptyString);
781
782 wxString projName = value.ToWString();
783 bool found = false;
784
785 // First try to load the data files based on the _data dir given in the .aup file
786 if (!projName.empty())
787 {
788 mProjDir.AppendDir(projName);
789 if (!mProjDir.DirExists())
790 {
791 mProjDir.RemoveLastDir();
792 projName.clear();
793 }
794 }
795
796 // If that fails then try to use the filename of the .aup as the base directory
797 // This is because unzipped projects e.g. those that get transferred between mac-pc
798 // may have encoding issues and end up expanding the wrong filenames for certain
799 // international characters (such as capital 'A' with an umlaut.)
800 if (projName.empty())
801 {
802 projName = altname;
803 mProjDir.AppendDir(projName);
804 if (!mProjDir.DirExists())
805 {
806 projName.clear();
807 }
808 }
809
810 // No luck...complain and bail
811 if (projName.empty())
812 {
814 XO("Couldn't find the project data folder: \"%s\"").Format(value.ToWString()));
815 return false;
816 }
817
818 // Collect and hash the file names within the project directory
819 wxArrayString files;
820 size_t cnt = wxDir::GetAllFiles(mProjDir.GetFullPath(),
821 &files,
822 "*.*");
823
824 for (const auto &fn : files)
825 {
826 mFileMap[wxFileNameFromPath(fn)] = {fn, {}};
827 }
828 }
829 else if (attr == "rate")
830 {
831 if (!value.TryGet(dValue) || (dValue < 0.0))
832 {
833 return SetError(XO("Invalid project 'selLow' attribute."));
834 }
835
836 set(rate, dValue);
837 }
838
839 else if (attr == "snapto")
840 {
841 set(snapto, (value.ToWString() == "on" ? true : false));
842 }
843
844 else if (attr == "selectionformat")
845 {
846 set(selectionformat, value.ToWString());
847 }
848
849 else if (attr == "frequencyformat")
850 {
851 set(frequencyformat, value.ToWString());
852 }
853
854 else if (attr == "bandwidthformat")
855 {
856 set(bandwidthformat, value.ToWString());
857 }
858#undef set
859 }
860
861 if (requiredTags < 3)
862 {
863 return false;
864 }
865
866 // Do not set the handler - already handled
867
868 return true;
869}
870
872{
873 handler = TrackList::Get(mProject).Add(std::make_shared<LabelTrack>());
874
875 return true;
876}
877
879{
880#if defined(USE_MIDI)
881 handler = TrackList::Get(mProject).Add(std::make_shared<NoteTrack>());
882
883 return true;
884#else
886 XO("MIDI tracks found in project file, but this build of Audacity does not include MIDI support, bypassing track."));
887 return false;
888#endif
889}
890
892{
894
895 // Bypass this timetrack if the project already has one
896 // (See HandleTimeEnvelope and HandleControlPoint also)
897 if (*tracks.Any<TimeTrack>().begin())
898 {
900 XO("The active project already has a time track and one was encountered in the project being imported, bypassing imported time track."));
901 return true;
902 }
903
904 handler =
905 TrackList::Get(mProject).Add(std::make_shared<TimeTrack>());
906
907 return true;
908}
909
911{
912 auto &trackFactory = WaveTrackFactory::Get(mProject);
914 TrackList::Get(mProject).Add(trackFactory.Create());
915
916 // No active clip. In early versions of Audacity, there was a single
917 // implied clip so we'll create a clip when the first "sequence" is
918 // found.
919 mClip = nullptr;
920
921 return true;
922}
923
925{
926 wxString n;
927 wxString v;
928
929 // Support for legacy tags
930 for (auto pair : mAttrs)
931 {
932 auto attr = pair.first;
933 auto value = pair.second;
934
935 if (attr == "id3v2")
936 {
937 continue;
938 }
939 else if (attr == "track")
940 {
941 n = wxT("TRACKNUMBER");
942 }
943 else
944 {
945 n = std::string(attr);
946 n.MakeUpper();
947 }
948
949 v = value.ToWString();
950
951 if (!v.empty())
952 mTags->SetTag(n, value.ToWString());
953 }
954
955 // Do not set the handler - already handled
956
957 return true;
958}
959
961{
962 if (mParentTag != "tags")
963 {
964 return false;
965 }
966
967 wxString n, v;
968
969 for (auto pair : mAttrs)
970 {
971 auto attr = pair.first;
972 auto value = pair.second;
973
974 if (attr == "name")
975 {
976 n = value.ToWString();
977 }
978 else if (attr == "value")
979 {
980 v = value.ToWString();
981 }
982 }
983
984 if (n == wxT("id3v2"))
985 {
986 // LLL: This is obsolete, but it must be handled and ignored.
987 }
988 else
989 {
990 mTags->SetTag(n, v);
991 }
992
993 // Do not set the handler - already handled
994
995 return true;
996}
997
999{
1000 if (mParentTag != "labeltrack")
1001 {
1002 return false;
1003 }
1004
1005 // The parent handler also handles this tag
1006 handler = mHandlers.back().handler;
1007
1008 return true;
1009}
1010
1012{
1013 struct node node = mHandlers.back();
1014
1015 if (mParentTag == "wavetrack")
1016 {
1017 WaveTrack *wavetrack = static_cast<WaveTrack *>(node.handler);
1018
1019 handler = wavetrack->CreateClip();
1020 }
1021 else if (mParentTag == "waveclip")
1022 {
1023 // Nested wave clips are cut lines
1024 WaveClip *waveclip = static_cast<WaveClip *>(node.handler);
1025
1026 handler = waveclip->HandleXMLChild(mCurrentTag);
1027 }
1028
1029 mClip = static_cast<WaveClip *>(handler);
1030 mClips.push_back(mClip);
1031
1032 return true;
1033}
1034
1036{
1037 struct node node = mHandlers.back();
1038
1039 if (mParentTag == "timetrack")
1040 {
1041 // If an imported timetrack was bypassed, then we want to bypass the
1042 // envelope as well. (See HandleTimeTrack and HandleControlPoint)
1043 if (node.handler)
1044 {
1045 TimeTrack *timetrack = static_cast<TimeTrack *>(node.handler);
1046
1047 handler = timetrack->GetEnvelope();
1048 }
1049 }
1050 // Earlier versions of Audacity had a single implied waveclip, so for
1051 // these versions, we get or create the only clip in the track.
1052 else if (mParentTag == "wavetrack")
1053 {
1055 }
1056 // Nested wave clips are cut lines
1057 else if (mParentTag == "waveclip")
1058 {
1059 WaveClip *waveclip = static_cast<WaveClip *>(node.handler);
1060
1061 handler = waveclip->GetEnvelope();
1062 }
1063
1064 return true;
1065}
1066
1068{
1069 struct node node = mHandlers.back();
1070
1071 if (mParentTag == "envelope")
1072 {
1073 // If an imported timetrack was bypassed, then we want to bypass the
1074 // control points as well. (See HandleTimeTrack and HandleEnvelope)
1075 if (node.handler)
1076 {
1077 Envelope *envelope = static_cast<Envelope *>(node.handler);
1078
1079 handler = envelope->HandleXMLChild(mCurrentTag);
1080 }
1081 }
1082
1083 return true;
1084}
1085
1087{
1088 struct node node = mHandlers.back();
1089
1090 WaveClip *waveclip = static_cast<WaveClip *>(node.handler);
1091
1092 // Earlier versions of Audacity had a single implied waveclip, so for
1093 // these versions, we get or create the only clip in the track.
1094 if (mParentTag == "wavetrack")
1095 {
1096 XMLTagHandler *dummy;
1097 HandleWaveClip(dummy);
1098 waveclip = mClip;
1099 }
1100
1101 auto pSequence =
1102 static_cast<Sequence*>(waveclip->HandleXMLChild("sequence"));
1103
1104 for (auto pair : mAttrs) {
1105 auto attr = pair.first;
1106 auto value = pair.second;
1107
1108 if (attr == "maxsamples")
1109 {
1110 // This attribute is a sample count, so can be 64bit
1111 long long llvalue;
1112 if (!value.TryGet(llvalue) || (llvalue < 0))
1113 {
1114 return SetError(XO("Invalid sequence 'maxsamples' attribute."));
1115 }
1116
1117 // Dominic, 12/10/2006:
1118 // Let's check that maxsamples is >= 1024 and <= 64 * 1024 * 1024
1119 // - that's a pretty wide range of reasonable values.
1120 if ((llvalue < 1024) || (llvalue > 64 * 1024 * 1024))
1121 {
1122 return SetError(XO("Invalid sequence 'maxsamples' attribute."));
1123 }
1124 }
1125 else if (attr == "sampleformat")
1126 {
1127 // This attribute is a sample format, normal int
1128 long fValue;
1129 if (!value.TryGet(fValue) || (fValue < 0) || !Sequence::IsValidSampleFormat(fValue))
1130 {
1131 return SetError(XO("Invalid sequence 'sampleformat' attribute."));
1132 }
1133
1134 mFormat = (sampleFormat) fValue;
1135 // Assume old AUP format file never had wide clips
1136 pSequence->ConvertToSampleFormat(mFormat);
1137 }
1138 else if (attr == "numsamples")
1139 {
1140 // This attribute is a sample count, so can be 64bit
1141 long long llvalue;
1142 if (!value.TryGet(llvalue) || (llvalue < 0))
1143 {
1144 return SetError(XO("Invalid sequence 'numsamples' attribute."));
1145 }
1146 }
1147 }
1148
1149 // Do not set the handler - already handled
1150
1151 return true;
1152}
1153
1155{
1156 for (auto pair : mAttrs)
1157 {
1158 auto attr = pair.first;
1159 auto value = pair.second;
1160
1161 if (attr == "start")
1162 {
1163 // making sure that values > 2^31 are OK because long clips will need them.
1164 long long llvalue;
1165 if (!value.TryGet(llvalue) || (llvalue < 0))
1166 {
1167 return SetError(XO("Unable to parse the waveblock 'start' attribute"));
1168 }
1169 }
1170 }
1171
1172 // Do not set the handler - already handled
1173
1174 return true;
1175}
1176
1178{
1179 FilePath filename;
1180 size_t len = 0;
1181
1182 for (auto pair : mAttrs)
1183 {
1184 auto attr = pair.first;
1185 auto value = pair.second;
1186
1187 // Can't use XMLValueChecker::IsGoodFileName here, but do part of its test.
1188 if (CaseInsensitiveEquals(attr, "filename"))
1189 {
1190 const wxString strValue = value.ToWString();
1191
1193 {
1194 if (mFileMap.find(strValue) != mFileMap.end())
1195 {
1196 filename = mFileMap[strValue].first;
1197 }
1198 else
1199 {
1200 SetWarning(XO("Missing project file %s\n\nInserting silence instead.")
1201 .Format(strValue));
1202 }
1203 }
1204 }
1205 else if (attr == "len")
1206 {
1207 long lValue;
1208 if (!value.TryGet(lValue) || (lValue <= 0))
1209 {
1210 return SetError(XO("Missing or invalid simpleblockfile 'len' attribute."));
1211 }
1212
1213 len = lValue;
1214 }
1215 }
1216
1217 // Do not set the handler - already handled
1218
1219 AddFile(len, mFormat, filename, filename);
1220
1221 return true;
1222}
1223
1225{
1226 FilePath filename;
1227 size_t len = 0;
1228
1229 for (auto pair : mAttrs)
1230 {
1231 auto attr = pair.first;
1232 auto value = pair.second;
1233
1234 if (attr == "len")
1235 {
1236 long lValue;
1237 if (!value.TryGet(lValue) || !(lValue > 0))
1238 {
1239 return SetError(XO("Missing or invalid silentblockfile 'len' attribute."));
1240 }
1241
1242 len = lValue;
1243 }
1244 }
1245
1246 // Do not set the handler - already handled
1247
1248 AddFile(len, mFormat);
1249
1250 return true;
1251}
1252
1254{
1255 wxString summaryFilename;
1256 wxFileName filename;
1257 sampleCount start = 0;
1258 size_t len = 0;
1259 int channel = 0;
1260 wxString name;
1261
1262 for (auto pair : mAttrs)
1263 {
1264 auto attr = pair.first;
1265 auto value = pair.second;
1266
1267 if (CaseInsensitiveEquals(attr, "aliasfile"))
1268 {
1269 const wxString strValue = value.ToWString();
1270
1271 if (XMLValueChecker::IsGoodPathName(strValue))
1272 {
1273 filename.Assign(strValue);
1274 }
1275 else if (XMLValueChecker::IsGoodFileName(strValue, mProjDir.GetPath()))
1276 {
1277 // Allow fallback of looking for the file name, located in the data directory.
1278 filename.Assign(mProjDir.GetPath(), strValue);
1279 }
1280 else if (XMLValueChecker::IsGoodPathString(strValue))
1281 {
1282 // If the aliased file is missing, we failed XMLValueChecker::IsGoodPathName()
1283 // and XMLValueChecker::IsGoodFileName, because both do existence tests.
1284 SetWarning(XO("Missing alias file %s\n\nInserting silence instead.")
1285 .Format(strValue));
1286 }
1287 }
1288 else if (CaseInsensitiveEquals(attr, "summaryfile"))
1289 {
1290 summaryFilename = value.ToWString();
1291 }
1292 else if (CaseInsensitiveEquals(attr, "aliasstart"))
1293 {
1294 long long llValue;
1295 if (!value.TryGet(llValue) || (llValue < 0))
1296 {
1297 return SetError(XO("Missing or invalid pcmaliasblockfile 'aliasstart' attribute."));
1298 }
1299
1300 start = llValue;
1301 }
1302 else if (CaseInsensitiveEquals(attr, "aliaslen"))
1303 {
1304 long lValue;
1305 if (!value.TryGet(lValue) || (lValue <= 0))
1306 {
1307 return SetError(XO("Missing or invalid pcmaliasblockfile 'aliaslen' attribute."));
1308 }
1309
1310 len = lValue;
1311 }
1312 else if (CaseInsensitiveEquals(attr, "aliaschannel"))
1313 {
1314 long lValue;
1315 if (!value.TryGet(lValue) || (lValue < 0))
1316 {
1317 return SetError(XO("Missing or invalid pcmaliasblockfile 'aliaslen' attribute."));
1318 }
1319
1320 channel = lValue;
1321 }
1322 }
1323
1324 // Do not set the handler - already handled
1325
1326 if (filename.IsOk())
1327 AddFile(len, mFormat,
1328 summaryFilename, filename.GetFullPath(),
1329 start, channel);
1330 else
1331 AddFile(len, mFormat); // will add silence instead
1332
1333 return true;
1334}
1335
1337{
1338 // Adapted from ImportXMLTagHandler::HandleXMLTag as in version 2.4.2
1339 if (mAttrs.empty() || mAttrs.front().first != "filename")
1340 return false;
1341
1342 wxString strAttr = mAttrs.front().second.ToWString();
1343
1344 if (!XMLValueChecker::IsGoodPathName(strAttr))
1345 {
1346 // Maybe strAttr is just a fileName, not the full path. Try the project data directory.
1347 wxFileNameWrapper fileName0{ GetFilename() };
1348 fileName0.SetExt({});
1349 wxFileNameWrapper fileName{
1350 fileName0.GetFullPath() + wxT("_data"), strAttr };
1351 if (XMLValueChecker::IsGoodFileName(strAttr, fileName.GetPath(wxPATH_GET_VOLUME)))
1352 strAttr = fileName.GetFullPath();
1353 else
1354 {
1355 wxLogWarning(wxT("Could not import file: %s"), strAttr);
1356 return false;
1357 }
1358 }
1359
1361 auto oldNumTracks = tracks.Size();
1362 Track *pLast = nullptr;
1363 if (oldNumTracks > 0)
1364 pLast = *tracks.rbegin();
1365
1366 // Guard this call so that C++ exceptions don't propagate through
1367 // the expat library
1369 [&] { ProjectFileManager::Get(mProject).Import(strAttr, false); },
1370 [&](AudacityException*) {});
1371
1372 if (oldNumTracks == tracks.Size())
1373 return false;
1374
1375 // Handle other attributes, now that we have the tracks.
1376 // Apply them to all new wave tracks.
1377 bool bSuccess = true;
1378
1379 auto range = tracks.Any();
1380 if (pLast) {
1381 range = range.StartingWith(pLast);
1382 ++range.first;
1383 }
1384
1385 mAttrs.erase(mAttrs.begin());
1386
1387 for (auto pTrack: range.Filter<WaveTrack>()) {
1388 // Most of the "import" tag attributes are the same as for "wavetrack" tags,
1389 // so apply them via WaveTrack::HandleXMLTag().
1390 bSuccess = pTrack->HandleXMLTag("wavetrack", mAttrs);
1391
1392 // "offset" tag is ignored in WaveTrack::HandleXMLTag except for legacy projects,
1393 // so handle it here.
1394 double dblValue;
1395 for (auto pair : mAttrs) {
1396 auto attr = pair.first;
1397 auto value = pair.second;
1398 if (attr == "offset" && value.TryGet(dblValue))
1399 pTrack->MoveTo(dblValue);
1400 }
1401 }
1402 return bSuccess;
1403}
1404
1407 const FilePath &blockFilename /* = wxEmptyString */,
1408 const FilePath &audioFilename /* = wxEmptyString */,
1409 sampleCount origin /* = 0 */,
1410 int channel /* = 0 */)
1411{
1412 fileinfo fi = {};
1413 fi.track = mWaveTrack;
1414 fi.clip = mClip;
1415 fi.blockFile = blockFilename;
1416 fi.audioFile = audioFilename;
1417 fi.len = len;
1418 fi.format = format,
1419 fi.origin = origin,
1420 fi.channel = channel;
1421
1422 mFiles.push_back(fi);
1423
1424 mTotalSamples += len;
1425}
1426
1428{
1429 wxASSERT(mClip || mWaveTrack);
1430
1431 if (mClip)
1432 {
1434 }
1435 else if (mWaveTrack)
1436 {
1437 // Assume alignment of clips and insert silence into leader only
1438 if (mWaveTrack->IsLeader())
1441 }
1442
1443 return true;
1444}
1445
1446// All errors that occur here will simply insert silence and allow the
1447// import to continue.
1449 const FilePath &audioFilename,
1450 sampleCount len,
1452 sampleCount origin /* = 0 */,
1453 int channel /* = 0 */)
1454{
1455 auto pClip = mClip ? mClip : mWaveTrack->RightmostOrNewClip();
1456 auto &pBlock = mFileMap[wxFileNameFromPath(blockFilename)].second;
1457 if (pBlock) {
1458 // Replicate the sharing of blocks
1459 if (pClip->GetWidth() != 1)
1460 return false;
1461 pClip->AppendSharedBlock( pBlock );
1462 return true;
1463 }
1464
1465 // Third party library has its own type alias, check it before
1466 // adding origin + size_t
1467 static_assert(sizeof(sampleCount::type) <= sizeof(sf_count_t),
1468 "Type sf_count_t is too narrow to hold a sampleCount");
1469
1470 SF_INFO info;
1471 memset(&info, 0, sizeof(info));
1472
1473 wxFile f; // will be closed when it goes out of scope
1474 SNDFILE *sf = nullptr;
1475 bool success = false;
1476
1477#ifndef UNCAUGHT_EXCEPTIONS_UNAVAILABLE
1478 const auto uncaughtExceptionsCount = std::uncaught_exceptions();
1479#endif
1480
1481 auto cleanup = finally([&]
1482 {
1483 // Do this before any throwing might happen
1484 if (sf)
1485 {
1486 SFCall<int>(sf_close, sf);
1487 }
1488
1489 if (!success)
1490 {
1491 SetWarning(XO("Error while processing %s\n\nInserting silence.").Format(audioFilename));
1492
1493 // If we are unwinding for an exception, don't do another
1494 // potentially throwing operation
1495#ifdef UNCAUGHT_EXCEPTIONS_UNAVAILABLE
1496 if (!std::uncaught_exception())
1497#else
1498 if (uncaughtExceptionsCount == std::uncaught_exceptions())
1499#endif
1500 // If this does throw, let that propagate, don't guard the call
1501 AddSilence(len);
1502 }
1503 });
1504
1505 if (!f.Open(audioFilename))
1506 {
1507 SetWarning(XO("Failed to open %s").Format(audioFilename));
1508
1509 return true;
1510 }
1511
1512 // Even though there is an sf_open() that takes a filename, use the one that
1513 // takes a file descriptor since wxWidgets can open a file with a Unicode name and
1514 // libsndfile can't (under Windows).
1515 sf = SFCall<SNDFILE*>(sf_open_fd, f.fd(), SFM_READ, &info, FALSE);
1516 if (!sf)
1517 {
1518 SetWarning(XO("Failed to open %s").Format(audioFilename));
1519
1520 return true;
1521 }
1522
1523 if (origin > 0)
1524 {
1525 if (SFCall<sf_count_t>(sf_seek, sf, origin.as_long_long(), SEEK_SET) < 0)
1526 {
1527 SetWarning(XO("Failed to seek to position %lld in %s")
1528 .Format(origin.as_long_long(), audioFilename));
1529
1530 return true;
1531 }
1532 }
1533
1534 sf_count_t cnt = len.as_size_t();
1535 int channels = info.channels;
1536
1537 wxASSERT(channels >= 1);
1538 wxASSERT(channel < channels);
1539
1540 SampleBuffer buffer(cnt, format);
1541 samplePtr bufptr = buffer.ptr();
1542
1543 size_t framesRead = 0;
1544
1545 // These cases preserve the logic formerly in BlockFile.cpp,
1546 // which was deleted at commit 98d1468.
1547 if (channels == 1 && format == int16Sample && sf_subtype_is_integer(info.format))
1548 {
1549 // If both the src and dest formats are integer formats,
1550 // read integers directly from the file, conversions not needed
1551 framesRead = SFCall<sf_count_t>(sf_readf_short, sf, (short *) bufptr, cnt);
1552 }
1553 else if (channels == 1 && format == int24Sample && sf_subtype_is_integer(info.format))
1554 {
1555 framesRead = SFCall<sf_count_t>(sf_readf_int, sf, (int *) bufptr, cnt);
1556 if (framesRead != cnt)
1557 {
1558 SetWarning(XO("Unable to read %lld samples from %s")
1559 .Format(cnt, audioFilename));
1560
1561 return true;
1562 }
1563
1564 // libsndfile gave us the 3 byte sample in the 3 most
1565 // significant bytes -- we want it in the 3 least
1566 // significant bytes.
1567 int *intPtr = (int *) bufptr;
1568 for (size_t i = 0; i < framesRead; i++)
1569 {
1570 intPtr[i] = intPtr[i] >> 8;
1571 }
1572 }
1573 else if (format == int16Sample && !sf_subtype_more_than_16_bits(info.format))
1574 {
1575 // Special case: if the file is in 16-bit (or less) format,
1576 // and the calling method wants 16-bit data, go ahead and
1577 // read 16-bit data directly. This is a pretty common
1578 // case, as most audio files are 16-bit.
1579 SampleBuffer temp(cnt * channels, int16Sample);
1580 short *tmpptr = (short *) temp.ptr();
1581
1582 framesRead = SFCall<sf_count_t>(sf_readf_short, sf, tmpptr, cnt);
1583 if (framesRead != cnt)
1584 {
1585 SetWarning(XO("Unable to read %lld samples from %s")
1586 .Format(cnt, audioFilename));
1587
1588 return true;
1589 }
1590
1591 for (size_t i = 0; i < framesRead; i++)
1592 {
1593 ((short *)bufptr)[i] = tmpptr[(channels * i) + channel];
1594 }
1595 }
1596 else
1597 {
1598 /*
1599 Therefore none of the three cases above:
1600 !(channels == 1 && format == int16Sample && sf_subtype_is_integer(info.format))
1601 &&
1602 !(channels == 1 && format == int24Sample && sf_subtype_is_integer(info.format))
1603 &&
1604 !(format == int16Sample && !sf_subtype_more_than_16_bits(info.format))
1605
1606 So format is not 16 bits with wider file format (third conjunct),
1607 but still maybe it is 24 bits with float file format (second conjunct).
1608 */
1609
1610 // Otherwise, let libsndfile handle the conversion and
1611 // scaling, and pass us normalized data as floats. We can
1612 // then convert to whatever format we want.
1613 SampleBuffer tmpbuf(cnt * channels, floatSample);
1614 float *tmpptr = (float *) tmpbuf.ptr();
1615
1616 framesRead = SFCall<sf_count_t>(sf_readf_float, sf, tmpptr, cnt);
1617 if (framesRead != cnt)
1618 {
1619 SetWarning(XO("Unable to read %lld samples from %s")
1620 .Format(cnt, audioFilename));
1621
1622 return true;
1623 }
1624
1625 /*
1626 Dithering will happen in CopySamples if format is 24 bits.
1627 Should that be done?
1628
1629 Either the file is an ordinary simple block file -- and presumably the
1630 track was saved specifying a matching format, so format is float and
1631 there is no dithering.
1632
1633 Or else this is the very unusual case of an .auf file, importing PCM data
1634 on demand. The destination format is narrower, requiring dither, only
1635 if the user also specified a narrow format for the track. In such a
1636 case, dithering is right.
1637 */
1638 CopySamples((samplePtr)(tmpptr + channel),
1640 bufptr,
1641 format,
1642 framesRead,
1643 gHighQualityDither /* high quality by default */,
1644 channels /* source stride */);
1645 }
1646
1647 wxASSERT(mClip || mWaveTrack);
1648
1649 // Add the samples to the clip/track
1650 if (pClip)
1651 {
1652 if (pClip->GetWidth() != 1)
1653 return false;
1654 pBlock = pClip->AppendNewBlock(bufptr, format, cnt);
1655 }
1656
1657 // Let the finally block know everything is good
1658 success = true;
1659
1660 return true;
1661}
1662
1664{
1665 wxLogError(msg.Debug());
1666
1667 if (mErrorMsg.empty() || !mHasParseError)
1668 {
1669 mErrorMsg = msg;
1670 }
1671
1672 mHasParseError = true;
1673 return false;
1674}
1675
1677{
1678 wxLogWarning(msg.Debug());
1679
1680 if (mErrorMsg.empty())
1681 {
1682 mErrorMsg = msg;
1683 }
1684
1685 return false;
1686}
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...
const TranslatableString name
Definition: Distortion.cpp:76
bool sf_subtype_is_integer(unsigned int format)
bool sf_subtype_more_than_16_bits(unsigned int format)
XO("Cut/Copy/Paste")
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:65
The interface that all file import "plugins" (if you want to call them that) must implement....
std::vector< std::shared_ptr< TrackList > > TrackHolders
Definition: ImportRaw.h:24
wxString FilePath
Definition: Project.h:21
an object holding per-project preferred sample rate
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:57
const auto tracks
const auto project
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:83
TranslatableString mErrorMsg
Definition: ImportAUP.cpp:217
bool AddSamples(const FilePath &blockFilename, const FilePath &audioFilename, sampleCount len, sampleFormat format, sampleCount origin=0, int channel=0)
Definition: ImportAUP.cpp:1448
struct AUPImportFileHandle::@137 mProjectAttrs
sampleFormat mFormat
Definition: ImportAUP.cpp:200
std::string mParentTag
Definition: ImportAUP.cpp:204
bool HandlePCMAliasBlockFile(XMLTagHandler *&handle)
Definition: ImportAUP.cpp:1253
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:301
AudacityProject & mProject
Definition: ImportAUP.cpp:160
bool HandleProject(XMLTagHandler *&handle)
Definition: ImportAUP.cpp:681
bool HandleSilentBlockFile(XMLTagHandler *&handle)
Definition: ImportAUP.cpp:1224
bool HandleLabel(XMLTagHandler *&handle)
Definition: ImportAUP.cpp:998
void HandleXMLEndTag(const std::string_view &tag) override
Definition: ImportAUP.cpp:555
bool HandleWaveBlock(XMLTagHandler *&handle)
Definition: ImportAUP.cpp:1154
bool HandleLabelTrack(XMLTagHandler *&handle)
Definition: ImportAUP.cpp:871
WaveTrack * mWaveTrack
Definition: ImportAUP.cpp:213
bool HandleXMLTag(const std::string_view &tag, const AttributesList &attrs) override
Definition: ImportAUP.cpp:587
wxFileName mProjDir
Definition: ImportAUP.cpp:208
std::vector< WaveClip * > mClips
Definition: ImportAUP.cpp:215
TranslatableString GetFileDescription() override
Definition: ImportAUP.cpp:291
TranslatableString GetErrorMessage() const override
Definition: ImportAUP.cpp:296
std::map< wxString, std::pair< FilePath, std::shared_ptr< SampleBlock > > > BlockFileMap
Definition: ImportAUP.cpp:210
bool HandleSequence(XMLTagHandler *&handle)
Definition: ImportAUP.cpp:1086
bool SetError(const TranslatableString &msg)
Definition: ImportAUP.cpp:1663
bool HandleWaveTrack(XMLTagHandler *&handle)
Definition: ImportAUP.cpp:910
wxInt32 GetStreamCount() override
Definition: ImportAUP.cpp:501
sampleCount mTotalSamples
Definition: ImportAUP.cpp:198
std::vector< struct node > stack
Definition: ImportAUP.cpp:115
bool HandleNoteTrack(XMLTagHandler *&handle)
Definition: ImportAUP.cpp:878
bool SetWarning(const TranslatableString &msg)
Definition: ImportAUP.cpp:1676
void Import(ImportProgressListener &progressListener, WaveTrackFactory *trackFactory, TrackHolders &outTracks, Tags *tags, std::optional< LibFileFormats::AcidizerTags > &outAcidTags) override
Definition: ImportAUP.cpp:307
void SetStreamUsage(wxInt32 WXUNUSED(StreamID), bool WXUNUSED(Use)) override
Definition: ImportAUP.cpp:512
bool HandleTimeTrack(XMLTagHandler *&handle)
Definition: ImportAUP.cpp:891
bool HandleControlPoint(XMLTagHandler *&handle)
Definition: ImportAUP.cpp:1067
bool HandleImport(XMLTagHandler *&handle)
Definition: ImportAUP.cpp:1336
bool HandleWaveClip(XMLTagHandler *&handle)
Definition: ImportAUP.cpp:1011
bool HandleTag(XMLTagHandler *&handle)
Definition: ImportAUP.cpp:960
std::vector< fileinfo > mFiles
Definition: ImportAUP.cpp:197
bool HandleSimpleBlockFile(XMLTagHandler *&handle)
Definition: ImportAUP.cpp:1177
std::string mCurrentTag
Definition: ImportAUP.cpp:205
const TranslatableStrings & GetStreamInfo() override
Definition: ImportAUP.cpp:506
bool HandleTags(XMLTagHandler *&handle)
Definition: ImportAUP.cpp:924
bool AddSilence(sampleCount len)
Definition: ImportAUP.cpp:1427
bool HandleEnvelope(XMLTagHandler *&handle)
Definition: ImportAUP.cpp:1035
XMLTagHandler * HandleXMLChild(const std::string_view &tag) override
Definition: ImportAUP.cpp:550
void AddFile(sampleCount len, sampleFormat format, const FilePath &blockFilename=wxEmptyString, const FilePath &audioFilename=wxEmptyString, sampleCount origin=0, int channel=0)
Definition: ImportAUP.cpp:1405
AttributesList mAttrs
Definition: ImportAUP.cpp:206
An ImportPlugin for AUP files (pre-AUP3)
Definition: ImportAUP.cpp:68
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:334
Abstract base class used in importing a file.
bool IsStopped() const noexcept
FilePath GetFilename() const override
bool IsCancelled() const noexcept
unsigned long long ByteCount
Definition: ImportPlugin.h:114
Base class for FlacImportPlugin, LOFImportPlugin, MP3ImportPlugin, OggImportPlugin and PCMImportPlugi...
Definition: ImportPlugin.h:67
Interface used to report on import state and progress.
virtual void OnImportResult(ImportResult result)=0
Used to report on import result for file handle passed as argument to OnImportFileOpened.
virtual void OnImportProgress(double progress)=0
static void ShowMessageBox(const TranslatableString &message, const TranslatableString &caption=XO("Import Project"))
Definition: ImportUtils.cpp:43
static void FixTracks(TrackList &tracks, const std::function< void(const TranslatableString &)> &onError, const std::function< void(const TranslatableString &)> &onUnlink)
Attempts to find and fix problems in tracks.
bool Import(const std::vector< FilePath > &fileNames, bool addToHistory=true)
static ProjectFileManager & Get(AudacityProject &project)
static ProjectHistory & Get(AudacityProject &project)
static ProjectNumericFormats & Get(AudacityProject &project)
static ProjectRate & Get(AudacityProject &project)
Definition: ProjectRate.cpp:28
void SetRate(double rate)
Definition: ProjectRate.cpp:58
void SetSnapMode(SnapMode mode)
Definition: ProjectSnap.cpp:41
static ProjectSnap & Get(AudacityProject &project)
Definition: ProjectSnap.cpp:27
samplePtr ptr() const
Definition: SampleFormat.h:165
static const int UndefinedFrequency
A WaveTrack contains WaveClip(s). A WaveClip contains a Sequence. A Sequence is primarily an interfac...
Definition: Sequence.h:53
static bool IsValidSampleFormat(const int nValue)
true if nValue is one of the sampleFormat enum values
Definition: Sequence.cpp:1875
ID3 Tags (for MP3)
Definition: Tags.h:73
void SetTag(const wxString &name, const wxString &value, const bool bSpecialTag=false)
Definition: Tags.cpp:431
A kind of Track used to 'warp time'.
Definition: TimeTrack.h:24
BoundedEnvelope * GetEnvelope()
Definition: TimeTrack.h:83
Abstract base class for an object holding data associated with points on a time axis.
Definition: Track.h:122
TrackKind * Add(const std::shared_ptr< TrackKind > &t)
Definition: Track.h:1201
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:347
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:113
XMLTagHandler * HandleXMLChild(const std::string_view &tag) override
Definition: WaveClip.cpp:644
double GetPlayEndTime() const override
Definition: WaveClip.cpp:1315
void InsertSilence(double t, double len, double *pEnvelopeValue=nullptr)
Definition: WaveClip.cpp:810
Envelope * GetEnvelope()
Definition: WaveClip.h:411
Used to create or clone a WaveTrack, with appropriate context from the project that will own the trac...
Definition: WaveTrack.h:1279
static WaveTrackFactory & Get(AudacityProject &project)
Definition: WaveTrack.cpp:4516
A Track that contains audio waveform data.
Definition: WaveTrack.h:227
void InsertSilence(double t, double len) override
Definition: WaveTrack.cpp:2477
WaveClip * CreateClip(double offset=.0, const wxString &name=wxEmptyString)
Create new clip and add it to this track.
Definition: WaveTrack.cpp:3801
bool IsLeader() const override
Definition: WaveTrack.cpp:2820
void SetLegacyFormat(sampleFormat format)
Definition: WaveTrack.cpp:2783
double GetEndTime() const override
Implement WideSampleSequence.
Definition: WaveTrack.cpp:3092
WaveClip * RightmostOrNewClip()
Get access to the last (rightmost) clip, or create a clip, if there is not already one.
Definition: WaveTrack.cpp:3831
double LongSamplesToTime(sampleCount pos) const
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
double as_double() const
Definition: SampleCount.h:46
Extend wxArrayString with move operations and construction and insertion fromstd::initializer_list.
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