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"
35#include "ProjectRate.h"
37#include "ProjectSettings.h"
38#include "ProjectSnap.h"
39#include "ProjectWindows.h"
40#include "Sequence.h"
41#include "Tags.h"
42#include "TimeTrack.h"
43#include "ViewInfo.h"
44#include "WaveClip.h"
45#include "WaveTrack.h"
48#include "XMLFileReader.h"
49#include "wxFileNameWrapper.h"
50#include "ImportUtils.h"
51
53
54#include <map>
55
56#define DESC XO("AUP project files (*.aup)")
57
58static const auto exts = {wxT("aup")};
59
60#include <wx/dir.h>
61#include <wx/ffile.h>
62#include <wx/file.h>
63#include <wx/log.h>
64#include <wx/string.h>
65
67using ImportHandle = std::unique_ptr<ImportFileHandle>;
68
69class AUPImportPlugin final : public ImportPlugin
70{
71public:
74
75 wxString GetPluginStringID() override;
76
78
79 ImportHandle Open(const FilePath &fileName,
80 AudacityProject *project) override;
81};
82
84 public XMLTagHandler
85{
86public:
90
91 TranslatableString GetErrorMessage() const override;
92
94
96
97 void Import(ImportProgressListener& progressListener,
98 WaveTrackFactory *trackFactory,
99 TrackHolders &outTracks,
100 Tags *tags) override;
101
102 wxInt32 GetStreamCount() override;
103
104 const TranslatableStrings &GetStreamInfo() override;
105
106 void SetStreamUsage(wxInt32 WXUNUSED(StreamID), bool WXUNUSED(Use)) override;
107
108 bool Open();
109
110private:
111 struct node
112 {
113 wxString parent;
114 wxString tag;
116 };
117 using stack = std::vector<struct node>;
118
119 bool HandleXMLTag(const std::string_view& tag, const AttributesList &attrs) override;
120 void HandleXMLEndTag(const std::string_view& tag) override;
121 XMLTagHandler *HandleXMLChild(const std::string_view& tag) override;
122
123 bool HandleProject(XMLTagHandler *&handle);
124 bool HandleLabelTrack(XMLTagHandler *&handle);
125 bool HandleNoteTrack(XMLTagHandler *&handle);
126 bool HandleTimeTrack(XMLTagHandler *&handle);
127 bool HandleWaveTrack(XMLTagHandler *&handle);
128 bool HandleTags(XMLTagHandler *&handle);
129 bool HandleTag(XMLTagHandler *&handle);
130 bool HandleLabel(XMLTagHandler *&handle);
131 bool HandleWaveClip(XMLTagHandler *&handle);
132 bool HandleSequence(XMLTagHandler *&handle);
133 bool HandleWaveBlock(XMLTagHandler *&handle);
134 bool HandleEnvelope(XMLTagHandler *&handle);
135 bool HandleControlPoint(XMLTagHandler *&handle);
139 bool HandleImport(XMLTagHandler *&handle);
140
141 // Called in first pass to collect information about blocks
142 void AddFile(sampleCount len,
144 const FilePath &blockFilename = wxEmptyString,
145 const FilePath &audioFilename = wxEmptyString,
146 sampleCount origin = 0,
147 int channel = 0);
148
149 // These two use the collected file information in a second pass
150 bool AddSilence(sampleCount len);
151 bool AddSamples(const FilePath &blockFilename,
152 const FilePath &audioFilename,
153 sampleCount len,
155 sampleCount origin = 0,
156 int channel = 0);
157
158 bool SetError(const TranslatableString &msg);
159 bool SetWarning(const TranslatableString &msg);
160
161private:
164
165 // project tag values that will be set in the actual project if the
166 // import is successful
167 #define field(n, t) bool have##n; t n
168 struct
169 {
170 field(vpos, int);
171 field(h, double);
172 field(zoom, double);
173 field(sel0, double);
174 field(sel1, double);
175#ifdef EXPERIMENTAL_SPECTRAL_EDITING
177 field(selHigh, double) = SelectedRegion::UndefinedFrequency;
178#endif
179 field(rate, double);
180 field(snapto, bool);
181 field(selectionformat, wxString);
182 field(audiotimeformat, wxString);
183 field(frequencyformat, wxString);
184 field(bandwidthformat, wxString);
186 #undef field
187
188 typedef struct
189 {
198 } fileinfo;
199 std::vector<fileinfo> mFiles;
201
203 unsigned long mNumChannels;
204
206 std::string mParentTag;
207 std::string mCurrentTag;
209
210 wxFileName mProjDir;
212 std::map<wxString, std::pair<FilePath, std::shared_ptr<SampleBlock>>>;
214
217 std::vector<WaveClip *> mClips;
218
220 bool mHasParseError { false };
221};
222
223namespace
224{
225// RHS is expected to be lowercase
227 const std::string_view& lhs, const std::string_view& rhsLower)
228{
229 if (lhs.length() != rhsLower.length())
230 return false;
231
232 for (size_t i = 0; i < lhs.length(); ++i)
233 if (std::tolower(lhs[i]) != rhsLower[i])
234 return false;
235
236 return true;
237}
238} // namespace
239
242{
243 static_assert(
244 sizeof(long long) >= sizeof(uint64_t) &&
245 sizeof(long) >= sizeof(uint32_t),
246 "Assumptions about sizes in XMLValueChecker calls are invalid!");
247}
248
250{
251}
252
254{
255 return wxT("legacyaup");
256}
257
259{
260 return DESC;
261}
262
265{
266 auto handle = std::make_unique<AUPImportFileHandle>(fileName, project);
267
268 if (!handle->Open())
269 {
270 // Error or not something that we recognize
271 return nullptr;
272 }
273
274 return handle;
275}
276
278{
279 "AUP", std::make_unique<AUPImportPlugin>()
280};
281
284: ImportFileHandleEx(fileName),
285 mProject(*project)
286{
287}
288
290{
291}
292
294{
295 return DESC;
296}
297
299{
300 return mErrorMsg;
301}
302
304{
305 // TODO: Get Uncompressed byte count.
306 return 0;
307}
308
312 Tags *tags)
313{
314 BeginImport();
315
316 mHasParseError = false;
317
318 auto &history = ProjectHistory::Get(mProject);
320 auto &viewInfo = ViewInfo::Get(mProject);
323
324 auto oldNumTracks = tracks.Size();
325 auto cleanup = finally([this, &tracks, oldNumTracks]{
326 if (mHasParseError || IsCancelled()) {
327 // Revoke additions of tracks
328 while (oldNumTracks < tracks.Size())
329 tracks.Remove(**tracks.end().advance(-1));
330 }
331 });
332
333 bool isDirty = history.GetDirty() || !tracks.empty();
334
335 mTotalSamples = 0;
336
337 mTags = tags;
338
339 XMLFileReader xmlFile;
340
341 bool success = xmlFile.Parse(this, GetFilename());
342 if (!success)
343 {
344 mErrorMsg = XO("Couldn't import the project:\n\n%s").Format(xmlFile.GetErrorStr());
346 return;
347 }
348
350 {
352 return;
353 }
354 else if(!mErrorMsg.empty())//i.e. warning
356
357 // TODO wide wave tracks -- quit here if misaligned tracks are found.
358 // (If we keep this entire source file at all)
359
360 sampleCount processed = 0;
361 for (auto fi : mFiles)
362 {
363 if(mTotalSamples.as_double() > 0)
364 progressListener.OnImportProgress(processed.as_double() / mTotalSamples.as_double());
365 if(IsCancelled())
366 {
368 return;
369 }
370 else if(IsStopped())
371 {
373 return;
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 if (!AddSamples(fi.blockFile, fi.audioFile,
385 fi.len, fi.format, fi.origin, fi.channel))
386 {
388 return;
389 }
390 }
391
392 processed += fi.len;
393 }
394
395 for (auto pClip : mClips)
396 pClip->UpdateEnvelopeTrackLen();
397
398 // If the active project is "dirty", then bypass the below updates as we don't
399 // want to going changing things the user may have already set up.
400 if (isDirty)
401 {
403 return;
404 }
405
406 if (mProjectAttrs.haverate)
408
409 if (mProjectAttrs.havesnapto)
410 {
413 }
414
415 if (mProjectAttrs.haveselectionformat)
416 {
417 selman.AS_SetSelectionFormat(NumericConverterFormats::Lookup(
419 mProjectAttrs.selectionformat));
420 }
421
422 if (mProjectAttrs.haveaudiotimeformat)
423 {
424 selman.TT_SetAudioTimeFormat(NumericConverterFormats::Lookup(
426 mProjectAttrs.audiotimeformat));
427 }
428
429 if (mProjectAttrs.havefrequencyformat)
430 {
431 selman.SSBL_SetFrequencySelectionFormatName(
435 mProjectAttrs.frequencyformat));
436 }
437
438 if (mProjectAttrs.havebandwidthformat)
439 {
440 selman.SSBL_SetBandwidthSelectionFormatName(
444 mProjectAttrs.bandwidthformat));
445 }
446
447 // PRL: It seems this must happen after SetSnapTo
448 if (mProjectAttrs.havevpos)
449 {
450 viewInfo.vpos = mProjectAttrs.vpos;
451 }
452
453 if (mProjectAttrs.haveh)
454 {
455 viewInfo.h = mProjectAttrs.h;
456 }
457
458 if (mProjectAttrs.havezoom)
459 {
460 viewInfo.SetZoom(mProjectAttrs.zoom);
461 }
462
463 if (mProjectAttrs.havesel0)
464 {
465 viewInfo.selectedRegion.setT0(mProjectAttrs.sel0);
466 }
467
468 if (mProjectAttrs.havesel1)
469 {
470 viewInfo.selectedRegion.setT1(mProjectAttrs.sel1);
471 }
472
473#ifdef EXPERIMENTAL_SPECTRAL_EDITING
474 if (mProjectAttrs.haveselLow)
475 {
476 viewInfo.selectedRegion.setF0(mProjectAttrs.selLow);
477 }
478
479 if (mProjectAttrs.haveselHigh)
480 {
481 viewInfo.selectedRegion.setF1(mProjectAttrs.selHigh);
482 }
483#endif
484
486}
487
489{
490 return 1;
491}
492
494{
495 static TranslatableStrings empty;
496 return empty;
497}
498
499void AUPImportFileHandle::SetStreamUsage(wxInt32 WXUNUSED(StreamID), bool WXUNUSED(Use))
500{
501}
502
504{
505 wxFFile ff(GetFilename(), wxT("rb"));
506 if (ff.IsOpened())
507 {
508 char buf[256];
509
510 int numRead = ff.Read(buf, sizeof(buf));
511
512 ff.Close();
513
514 buf[sizeof(buf) - 1] = '\0';
515
516 if (!wxStrncmp(buf, wxT("AudacityProject"), 15))
517 {
519 XO("This project was saved by Audacity version 1.0 or earlier. The format has\n"
520 "changed and this version of Audacity is unable to import the project.\n\n"
521 "Use a version of Audacity prior to v3.0.0 to upgrade the project and then\n"
522 "you may import it with this version of Audacity."));
523 return false;
524 }
525
526 if (wxStrncmp(buf, "<?xml", 5) == 0 &&
527 (wxStrstr(buf, "<audacityproject") ||
528 wxStrstr(buf, "<project") ))
529 {
530 return true;
531 }
532 }
533
534 return false;
535}
536
538{
539 return this;
540}
541
542void AUPImportFileHandle::HandleXMLEndTag(const std::string_view& tag)
543{
544 if (mHasParseError)
545 {
546 return;
547 }
548
549 struct node node = mHandlers.back();
550
551 if (tag == "waveclip")
552 {
553 mClip = nullptr;
554 }
555
556 if (node.handler)
557 {
559 }
560
561 mHandlers.pop_back();
562
563 if (mHandlers.size())
564 {
565 node = mHandlers.back();
568 }
569}
570
571bool AUPImportFileHandle::HandleXMLTag(const std::string_view& tag, const AttributesList &attrs)
572{
573 if (mHasParseError)
574 {
575 return false;
576 }
577
579 mCurrentTag = std::string(tag);
580 mAttrs = attrs;
581
582 XMLTagHandler *handler = nullptr;
583 bool success = false;
584
585 if (mCurrentTag == "project" ||
586 mCurrentTag == "audacityproject")
587 {
588 success = HandleProject(handler);
589 }
590 else if (mCurrentTag == "labeltrack")
591 {
592 success = HandleLabelTrack(handler);
593 }
594 else if (mCurrentTag == "notetrack")
595 {
596 success = HandleNoteTrack(handler);
597 }
598 else if (mCurrentTag == "timetrack")
599 {
600 success = HandleTimeTrack(handler);
601 }
602 else if (mCurrentTag == "wavetrack")
603 {
604 success = HandleWaveTrack(handler);
605 }
606 else if (mCurrentTag == "tags")
607 {
608 success = HandleTags(handler);
609 }
610 else if (mCurrentTag == "tag")
611 {
612 success = HandleTag(handler);
613 }
614 else if (mCurrentTag == "label")
615 {
616 success = HandleLabel(handler);
617 }
618 else if (mCurrentTag == "waveclip")
619 {
620 success = HandleWaveClip(handler);
621 }
622 else if (mCurrentTag == "sequence")
623 {
624 success = HandleSequence(handler);
625 }
626 else if (mCurrentTag == "waveblock")
627 {
628 success = HandleWaveBlock(handler);
629 }
630 else if (mCurrentTag == "envelope")
631 {
632 success = HandleEnvelope(handler);
633 }
634 else if (mCurrentTag == "controlpoint")
635 {
636 success = HandleControlPoint(handler);
637 }
638 else if (mCurrentTag == "simpleblockfile")
639 {
641 }
642 else if (mCurrentTag == "silentblockfile")
643 {
645 }
646 else if (mCurrentTag == "pcmaliasblockfile")
647 {
649 }
650 else if (mCurrentTag == "import")
651 {
652 success = HandleImport(handler);
653 }
654
655 if (!success || (handler && !handler->HandleXMLTag(tag, attrs)))
656 {
657 return SetError(XO("Internal error in importer...tag not recognized"));
658 }
659
661
662 return true;
663}
664
666{
667 auto &fileMan = ProjectFileManager::Get(mProject);
668 auto &window = GetProjectFrame(mProject);
669
670 int requiredTags = 0;
671
672 for (auto pair : mAttrs)
673 {
674 auto attr = pair.first;
675 auto value = pair.second;
676
677 double dValue;
678
679#define set(f, v) (mProjectAttrs.have ## f = true, mProjectAttrs.f = v)
680
681 // ViewInfo
682 if (attr == "vpos")
683 {
684 long lValue;
685 if (!value.TryGet(lValue) || (lValue < 0))
686 {
687 return SetError(XO("Invalid project 'vpos' attribute."));
688 }
689
690 set(vpos, (int) lValue);
691 }
692 else if (attr == "h")
693 {
694 if (!value.TryGet(dValue))
695 {
696 return SetError(XO("Invalid project 'h' attribute."));
697 }
698
699 set(h, dValue);
700 }
701 else if (attr == "zoom")
702 {
703 if (!value.TryGet(dValue) || (dValue < 0.0))
704 {
705 return SetError(XO("Invalid project 'zoom' attribute."));
706 }
707
708 set(zoom, dValue);
709 }
710 // Viewinfo.SelectedRegion
711 else if (attr == "sel0")
712 {
713 if (!value.TryGet(dValue))
714 {
715 return SetError(XO("Invalid project 'sel0' attribute."));
716 }
717
718 set(sel0, dValue);
719 }
720 else if (attr == "sel1")
721 {
722 if (!value.TryGet(dValue))
723 {
724 return SetError(XO("Invalid project 'sel1' attribute."));
725 }
726
727 set(sel1, dValue);
728 }
729#ifdef EXPERIMENTAL_SPECTRAL_EDITING
730 else if (attr == "selLow")
731 {
732 if (!value.TryGet(dValue) || (dValue < 0.0))
733 {
734 return SetError(XO("Invalid project 'selLow' attribute."));
735 }
736
737 set(selLow, dValue);
738 }
739 else if (attr == "selHigh")
740 {
741 if (!value.TryGet(dValue) || (dValue < 0.0))
742 {
743 return SetError(XO("Invalid project 'selHigh' attribute."));
744 }
745
746 set(selHigh, dValue);
747 }
748#endif
749 else if (attr == "version")
750 {
751 requiredTags++;
752 }
753
754 else if (attr == "audacityversion")
755 {
756 requiredTags++;
757 }
758 else if (attr == "projname")
759 {
760 requiredTags++;
761
763 wxString altname = mProjDir.GetName() + wxT("_data");
764 mProjDir.SetFullName(wxEmptyString);
765
766 wxString projName = value.ToWString();
767 bool found = false;
768
769 // First try to load the data files based on the _data dir given in the .aup file
770 if (!projName.empty())
771 {
772 mProjDir.AppendDir(projName);
773 if (!mProjDir.DirExists())
774 {
775 mProjDir.RemoveLastDir();
776 projName.clear();
777 }
778 }
779
780 // If that fails then try to use the filename of the .aup as the base directory
781 // This is because unzipped projects e.g. those that get transferred between mac-pc
782 // may have encoding issues and end up expanding the wrong filenames for certain
783 // international characters (such as capital 'A' with an umlaut.)
784 if (projName.empty())
785 {
786 projName = altname;
787 mProjDir.AppendDir(projName);
788 if (!mProjDir.DirExists())
789 {
790 projName.clear();
791 }
792 }
793
794 // No luck...complain and bail
795 if (projName.empty())
796 {
798 XO("Couldn't find the project data folder: \"%s\"").Format(value.ToWString()));
799 return false;
800 }
801
802 // Collect and hash the file names within the project directory
803 wxArrayString files;
804 size_t cnt = wxDir::GetAllFiles(mProjDir.GetFullPath(),
805 &files,
806 "*.*");
807
808 for (const auto &fn : files)
809 {
810 mFileMap[wxFileNameFromPath(fn)] = {fn, {}};
811 }
812 }
813 else if (attr == "rate")
814 {
815 if (!value.TryGet(dValue) || (dValue < 0.0))
816 {
817 return SetError(XO("Invalid project 'selLow' attribute."));
818 }
819
820 set(rate, dValue);
821 }
822
823 else if (attr == "snapto")
824 {
825 set(snapto, (value.ToWString() == "on" ? true : false));
826 }
827
828 else if (attr == "selectionformat")
829 {
830 set(selectionformat, value.ToWString());
831 }
832
833 else if (attr == "frequencyformat")
834 {
835 set(frequencyformat, value.ToWString());
836 }
837
838 else if (attr == "bandwidthformat")
839 {
840 set(bandwidthformat, value.ToWString());
841 }
842#undef set
843 }
844
845 if (requiredTags < 3)
846 {
847 return false;
848 }
849
850 // Do not set the handler - already handled
851
852 return true;
853}
854
856{
857 handler = TrackList::Get(mProject).Add(std::make_shared<LabelTrack>());
858
859 return true;
860}
861
863{
864#if defined(USE_MIDI)
865 handler = TrackList::Get(mProject).Add(std::make_shared<NoteTrack>());
866
867 return true;
868#else
870 XO("MIDI tracks found in project file, but this build of Audacity does not include MIDI support, bypassing track."));
871 return false;
872#endif
873}
874
876{
878
879 // Bypass this timetrack if the project already has one
880 // (See HandleTimeEnvelope and HandleControlPoint also)
881 if (*tracks.Any<TimeTrack>().begin())
882 {
884 XO("The active project already has a time track and one was encountered in the project being imported, bypassing imported time track."));
885 return true;
886 }
887
888 handler =
889 TrackList::Get(mProject).Add(std::make_shared<TimeTrack>());
890
891 return true;
892}
893
895{
896 auto &trackFactory = WaveTrackFactory::Get(mProject);
898 TrackList::Get(mProject).Add(trackFactory.Create());
899
900 // No active clip. In early versions of Audacity, there was a single
901 // implied clip so we'll create a clip when the first "sequence" is
902 // found.
903 mClip = nullptr;
904
905 return true;
906}
907
909{
910 wxString n;
911 wxString v;
912
913 // Support for legacy tags
914 for (auto pair : mAttrs)
915 {
916 auto attr = pair.first;
917 auto value = pair.second;
918
919 if (attr == "id3v2")
920 {
921 continue;
922 }
923 else if (attr == "track")
924 {
925 n = wxT("TRACKNUMBER");
926 }
927 else
928 {
929 n = std::string(attr);
930 n.MakeUpper();
931 }
932
933 v = value.ToWString();
934
935 if (!v.empty())
936 mTags->SetTag(n, value.ToWString());
937 }
938
939 // Do not set the handler - already handled
940
941 return true;
942}
943
945{
946 if (mParentTag != "tags")
947 {
948 return false;
949 }
950
951 wxString n, v;
952
953 for (auto pair : mAttrs)
954 {
955 auto attr = pair.first;
956 auto value = pair.second;
957
958 if (attr == "name")
959 {
960 n = value.ToWString();
961 }
962 else if (attr == "value")
963 {
964 v = value.ToWString();
965 }
966 }
967
968 if (n == wxT("id3v2"))
969 {
970 // LLL: This is obsolete, but it must be handled and ignored.
971 }
972 else
973 {
974 mTags->SetTag(n, v);
975 }
976
977 // Do not set the handler - already handled
978
979 return true;
980}
981
983{
984 if (mParentTag != "labeltrack")
985 {
986 return false;
987 }
988
989 // The parent handler also handles this tag
990 handler = mHandlers.back().handler;
991
992 return true;
993}
994
996{
997 struct node node = mHandlers.back();
998
999 if (mParentTag == "wavetrack")
1000 {
1001 WaveTrack *wavetrack = static_cast<WaveTrack *>(node.handler);
1002
1003 handler = wavetrack->CreateClip();
1004 }
1005 else if (mParentTag == "waveclip")
1006 {
1007 // Nested wave clips are cut lines
1008 WaveClip *waveclip = static_cast<WaveClip *>(node.handler);
1009
1010 handler = waveclip->HandleXMLChild(mCurrentTag);
1011 }
1012
1013 mClip = static_cast<WaveClip *>(handler);
1014 mClips.push_back(mClip);
1015
1016 return true;
1017}
1018
1020{
1021 struct node node = mHandlers.back();
1022
1023 if (mParentTag == "timetrack")
1024 {
1025 // If an imported timetrack was bypassed, then we want to bypass the
1026 // envelope as well. (See HandleTimeTrack and HandleControlPoint)
1027 if (node.handler)
1028 {
1029 TimeTrack *timetrack = static_cast<TimeTrack *>(node.handler);
1030
1031 handler = timetrack->GetEnvelope();
1032 }
1033 }
1034 // Earlier versions of Audacity had a single implied waveclip, so for
1035 // these versions, we get or create the only clip in the track.
1036 else if (mParentTag == "wavetrack")
1037 {
1039 }
1040 // Nested wave clips are cut lines
1041 else if (mParentTag == "waveclip")
1042 {
1043 WaveClip *waveclip = static_cast<WaveClip *>(node.handler);
1044
1045 handler = waveclip->GetEnvelope();
1046 }
1047
1048 return true;
1049}
1050
1052{
1053 struct node node = mHandlers.back();
1054
1055 if (mParentTag == "envelope")
1056 {
1057 // If an imported timetrack was bypassed, then we want to bypass the
1058 // control points as well. (See HandleTimeTrack and HandleEnvelope)
1059 if (node.handler)
1060 {
1061 Envelope *envelope = static_cast<Envelope *>(node.handler);
1062
1063 handler = envelope->HandleXMLChild(mCurrentTag);
1064 }
1065 }
1066
1067 return true;
1068}
1069
1071{
1072 struct node node = mHandlers.back();
1073
1074 WaveClip *waveclip = static_cast<WaveClip *>(node.handler);
1075
1076 // Earlier versions of Audacity had a single implied waveclip, so for
1077 // these versions, we get or create the only clip in the track.
1078 if (mParentTag == "wavetrack")
1079 {
1080 XMLTagHandler *dummy;
1081 HandleWaveClip(dummy);
1082 waveclip = mClip;
1083 }
1084
1085 auto pSequence =
1086 static_cast<Sequence*>(waveclip->HandleXMLChild("sequence"));
1087
1088 for (auto pair : mAttrs) {
1089 auto attr = pair.first;
1090 auto value = pair.second;
1091
1092 if (attr == "maxsamples")
1093 {
1094 // This attribute is a sample count, so can be 64bit
1095 long long llvalue;
1096 if (!value.TryGet(llvalue) || (llvalue < 0))
1097 {
1098 return SetError(XO("Invalid sequence 'maxsamples' attribute."));
1099 }
1100
1101 // Dominic, 12/10/2006:
1102 // Let's check that maxsamples is >= 1024 and <= 64 * 1024 * 1024
1103 // - that's a pretty wide range of reasonable values.
1104 if ((llvalue < 1024) || (llvalue > 64 * 1024 * 1024))
1105 {
1106 return SetError(XO("Invalid sequence 'maxsamples' attribute."));
1107 }
1108 }
1109 else if (attr == "sampleformat")
1110 {
1111 // This attribute is a sample format, normal int
1112 long fValue;
1113 if (!value.TryGet(fValue) || (fValue < 0) || !Sequence::IsValidSampleFormat(fValue))
1114 {
1115 return SetError(XO("Invalid sequence 'sampleformat' attribute."));
1116 }
1117
1118 mFormat = (sampleFormat) fValue;
1119 // Assume old AUP format file never had wide clips
1120 pSequence->ConvertToSampleFormat(mFormat);
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{ GetFilename() };
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
1345 auto oldNumTracks = tracks.Size();
1346 Track *pLast = nullptr;
1347 if (oldNumTracks > 0)
1348 pLast = *tracks.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 // Most of the "import" tag attributes are the same as for "wavetrack" tags,
1375 // so apply them via WaveTrack::HandleXMLTag().
1376 bSuccess = pTrack->HandleXMLTag("wavetrack", mAttrs);
1377
1378 // "offset" tag is ignored in WaveTrack::HandleXMLTag except for legacy projects,
1379 // so handle it here.
1380 double dblValue;
1381 for (auto pair : mAttrs) {
1382 auto attr = pair.first;
1383 auto value = pair.second;
1384 if (attr == "offset" && value.TryGet(dblValue))
1385 pTrack->MoveTo(dblValue);
1386 }
1387 }
1388 return bSuccess;
1389}
1390
1393 const FilePath &blockFilename /* = wxEmptyString */,
1394 const FilePath &audioFilename /* = wxEmptyString */,
1395 sampleCount origin /* = 0 */,
1396 int channel /* = 0 */)
1397{
1398 fileinfo fi = {};
1399 fi.track = mWaveTrack;
1400 fi.clip = mClip;
1401 fi.blockFile = blockFilename;
1402 fi.audioFile = audioFilename;
1403 fi.len = len;
1404 fi.format = format,
1405 fi.origin = origin,
1406 fi.channel = channel;
1407
1408 mFiles.push_back(fi);
1409
1410 mTotalSamples += len;
1411}
1412
1414{
1415 wxASSERT(mClip || mWaveTrack);
1416
1417 if (mClip)
1418 {
1420 }
1421 else if (mWaveTrack)
1422 {
1423 // Assume alignment of clips and insert silence into leader only
1424 if (mWaveTrack->IsLeader())
1427 }
1428
1429 return true;
1430}
1431
1432// All errors that occur here will simply insert silence and allow the
1433// import to continue.
1435 const FilePath &audioFilename,
1436 sampleCount len,
1438 sampleCount origin /* = 0 */,
1439 int channel /* = 0 */)
1440{
1441 auto pClip = mClip ? mClip : mWaveTrack->RightmostOrNewClip();
1442 auto &pBlock = mFileMap[wxFileNameFromPath(blockFilename)].second;
1443 if (pBlock) {
1444 // Replicate the sharing of blocks
1445 if (pClip->GetWidth() != 1)
1446 return false;
1447 pClip->AppendSharedBlock( pBlock );
1448 return true;
1449 }
1450
1451 // Third party library has its own type alias, check it before
1452 // adding origin + size_t
1453 static_assert(sizeof(sampleCount::type) <= sizeof(sf_count_t),
1454 "Type sf_count_t is too narrow to hold a sampleCount");
1455
1456 SF_INFO info;
1457 memset(&info, 0, sizeof(info));
1458
1459 wxFile f; // will be closed when it goes out of scope
1460 SNDFILE *sf = nullptr;
1461 bool success = false;
1462
1463#ifndef UNCAUGHT_EXCEPTIONS_UNAVAILABLE
1464 const auto uncaughtExceptionsCount = std::uncaught_exceptions();
1465#endif
1466
1467 auto cleanup = finally([&]
1468 {
1469 // Do this before any throwing might happen
1470 if (sf)
1471 {
1472 SFCall<int>(sf_close, sf);
1473 }
1474
1475 if (!success)
1476 {
1477 SetWarning(XO("Error while processing %s\n\nInserting silence.").Format(audioFilename));
1478
1479 // If we are unwinding for an exception, don't do another
1480 // potentially throwing operation
1481#ifdef UNCAUGHT_EXCEPTIONS_UNAVAILABLE
1482 if (!std::uncaught_exception())
1483#else
1484 if (uncaughtExceptionsCount == std::uncaught_exceptions())
1485#endif
1486 // If this does throw, let that propagate, don't guard the call
1487 AddSilence(len);
1488 }
1489 });
1490
1491 if (!f.Open(audioFilename))
1492 {
1493 SetWarning(XO("Failed to open %s").Format(audioFilename));
1494
1495 return true;
1496 }
1497
1498 // Even though there is an sf_open() that takes a filename, use the one that
1499 // takes a file descriptor since wxWidgets can open a file with a Unicode name and
1500 // libsndfile can't (under Windows).
1501 sf = SFCall<SNDFILE*>(sf_open_fd, f.fd(), SFM_READ, &info, FALSE);
1502 if (!sf)
1503 {
1504 SetWarning(XO("Failed to open %s").Format(audioFilename));
1505
1506 return true;
1507 }
1508
1509 if (origin > 0)
1510 {
1511 if (SFCall<sf_count_t>(sf_seek, sf, origin.as_long_long(), SEEK_SET) < 0)
1512 {
1513 SetWarning(XO("Failed to seek to position %lld in %s")
1514 .Format(origin.as_long_long(), audioFilename));
1515
1516 return true;
1517 }
1518 }
1519
1520 sf_count_t cnt = len.as_size_t();
1521 int channels = info.channels;
1522
1523 wxASSERT(channels >= 1);
1524 wxASSERT(channel < channels);
1525
1526 SampleBuffer buffer(cnt, format);
1527 samplePtr bufptr = buffer.ptr();
1528
1529 size_t framesRead = 0;
1530
1531 // These cases preserve the logic formerly in BlockFile.cpp,
1532 // which was deleted at commit 98d1468.
1533 if (channels == 1 && format == int16Sample && sf_subtype_is_integer(info.format))
1534 {
1535 // If both the src and dest formats are integer formats,
1536 // read integers directly from the file, conversions not needed
1537 framesRead = SFCall<sf_count_t>(sf_readf_short, sf, (short *) bufptr, cnt);
1538 }
1539 else if (channels == 1 && format == int24Sample && sf_subtype_is_integer(info.format))
1540 {
1541 framesRead = SFCall<sf_count_t>(sf_readf_int, sf, (int *) bufptr, cnt);
1542 if (framesRead != cnt)
1543 {
1544 SetWarning(XO("Unable to read %lld samples from %s")
1545 .Format(cnt, audioFilename));
1546
1547 return true;
1548 }
1549
1550 // libsndfile gave us the 3 byte sample in the 3 most
1551 // significant bytes -- we want it in the 3 least
1552 // significant bytes.
1553 int *intPtr = (int *) bufptr;
1554 for (size_t i = 0; i < framesRead; i++)
1555 {
1556 intPtr[i] = intPtr[i] >> 8;
1557 }
1558 }
1559 else if (format == int16Sample && !sf_subtype_more_than_16_bits(info.format))
1560 {
1561 // Special case: if the file is in 16-bit (or less) format,
1562 // and the calling method wants 16-bit data, go ahead and
1563 // read 16-bit data directly. This is a pretty common
1564 // case, as most audio files are 16-bit.
1565 SampleBuffer temp(cnt * channels, int16Sample);
1566 short *tmpptr = (short *) temp.ptr();
1567
1568 framesRead = SFCall<sf_count_t>(sf_readf_short, sf, tmpptr, cnt);
1569 if (framesRead != cnt)
1570 {
1571 SetWarning(XO("Unable to read %lld samples from %s")
1572 .Format(cnt, audioFilename));
1573
1574 return true;
1575 }
1576
1577 for (size_t i = 0; i < framesRead; i++)
1578 {
1579 ((short *)bufptr)[i] = tmpptr[(channels * i) + channel];
1580 }
1581 }
1582 else
1583 {
1584 /*
1585 Therefore none of the three cases above:
1586 !(channels == 1 && format == int16Sample && sf_subtype_is_integer(info.format))
1587 &&
1588 !(channels == 1 && format == int24Sample && sf_subtype_is_integer(info.format))
1589 &&
1590 !(format == int16Sample && !sf_subtype_more_than_16_bits(info.format))
1591
1592 So format is not 16 bits with wider file format (third conjunct),
1593 but still maybe it is 24 bits with float file format (second conjunct).
1594 */
1595
1596 // Otherwise, let libsndfile handle the conversion and
1597 // scaling, and pass us normalized data as floats. We can
1598 // then convert to whatever format we want.
1599 SampleBuffer tmpbuf(cnt * channels, floatSample);
1600 float *tmpptr = (float *) tmpbuf.ptr();
1601
1602 framesRead = SFCall<sf_count_t>(sf_readf_float, sf, tmpptr, cnt);
1603 if (framesRead != cnt)
1604 {
1605 SetWarning(XO("Unable to read %lld samples from %s")
1606 .Format(cnt, audioFilename));
1607
1608 return true;
1609 }
1610
1611 /*
1612 Dithering will happen in CopySamples if format is 24 bits.
1613 Should that be done?
1614
1615 Either the file is an ordinary simple block file -- and presumably the
1616 track was saved specifying a matching format, so format is float and
1617 there is no dithering.
1618
1619 Or else this is the very unusual case of an .auf file, importing PCM data
1620 on demand. The destination format is narrower, requiring dither, only
1621 if the user also specified a narrow format for the track. In such a
1622 case, dithering is right.
1623 */
1624 CopySamples((samplePtr)(tmpptr + channel),
1626 bufptr,
1627 format,
1628 framesRead,
1629 gHighQualityDither /* high quality by default */,
1630 channels /* source stride */);
1631 }
1632
1633 wxASSERT(mClip || mWaveTrack);
1634
1635 // Add the samples to the clip/track
1636 if (pClip)
1637 {
1638 if (pClip->GetWidth() != 1)
1639 return false;
1640 pBlock = pClip->AppendNewBlock(bufptr, format, cnt);
1641 }
1642
1643 // Let the finally block know everything is good
1644 success = true;
1645
1646 return true;
1647}
1648
1650{
1651 wxLogError(msg.Debug());
1652
1653 if (mErrorMsg.empty() || !mHasParseError)
1654 {
1655 mErrorMsg = msg;
1656 }
1657
1658 mHasParseError = true;
1659 return false;
1660}
1661
1663{
1664 wxLogWarning(msg.Debug());
1665
1666 if (mErrorMsg.empty())
1667 {
1668 mErrorMsg = msg;
1669 }
1670
1671 return false;
1672}
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:58
#define DESC
Definition: ImportAUP.cpp:56
#define field(n, t)
Definition: ImportAUP.cpp:167
#define set(f, v)
static Importer::RegisteredImportPlugin registered
Definition: ImportAUP.cpp:278
std::unique_ptr< ImportFileHandle > ImportHandle
Definition: ImportAUP.cpp:67
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
const NumericConverterType & NumericConverterType_BANDWIDTH()
const NumericConverterType & NumericConverterType_FREQUENCY()
const NumericConverterType & NumericConverterType_TIME()
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:55
const auto tracks
const auto project
static Settings & settings()
Definition: TrackInfo.cpp:83
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:85
TranslatableString mErrorMsg
Definition: ImportAUP.cpp:219
bool AddSamples(const FilePath &blockFilename, const FilePath &audioFilename, sampleCount len, sampleFormat format, sampleCount origin=0, int channel=0)
Definition: ImportAUP.cpp:1434
struct AUPImportFileHandle::@141 mProjectAttrs
sampleFormat mFormat
Definition: ImportAUP.cpp:202
std::string mParentTag
Definition: ImportAUP.cpp:206
bool HandlePCMAliasBlockFile(XMLTagHandler *&handle)
Definition: ImportAUP.cpp:1237
unsigned long mNumChannels
Definition: ImportAUP.cpp:203
AUPImportFileHandle(const FilePath &name, AudacityProject *project)
Definition: ImportAUP.cpp:282
BlockFileMap mFileMap
Definition: ImportAUP.cpp:213
ByteCount GetFileUncompressedBytes() override
Definition: ImportAUP.cpp:303
AudacityProject & mProject
Definition: ImportAUP.cpp:162
bool HandleProject(XMLTagHandler *&handle)
Definition: ImportAUP.cpp:665
bool HandleSilentBlockFile(XMLTagHandler *&handle)
Definition: ImportAUP.cpp:1208
bool HandleLabel(XMLTagHandler *&handle)
Definition: ImportAUP.cpp:982
void HandleXMLEndTag(const std::string_view &tag) override
Definition: ImportAUP.cpp:542
bool HandleWaveBlock(XMLTagHandler *&handle)
Definition: ImportAUP.cpp:1138
bool HandleLabelTrack(XMLTagHandler *&handle)
Definition: ImportAUP.cpp:855
WaveTrack * mWaveTrack
Definition: ImportAUP.cpp:215
bool HandleXMLTag(const std::string_view &tag, const AttributesList &attrs) override
Definition: ImportAUP.cpp:571
wxFileName mProjDir
Definition: ImportAUP.cpp:210
std::vector< WaveClip * > mClips
Definition: ImportAUP.cpp:217
TranslatableString GetFileDescription() override
Definition: ImportAUP.cpp:293
TranslatableString GetErrorMessage() const override
Definition: ImportAUP.cpp:298
std::map< wxString, std::pair< FilePath, std::shared_ptr< SampleBlock > > > BlockFileMap
Definition: ImportAUP.cpp:212
bool HandleSequence(XMLTagHandler *&handle)
Definition: ImportAUP.cpp:1070
bool SetError(const TranslatableString &msg)
Definition: ImportAUP.cpp:1649
bool HandleWaveTrack(XMLTagHandler *&handle)
Definition: ImportAUP.cpp:894
wxInt32 GetStreamCount() override
Definition: ImportAUP.cpp:488
sampleCount mTotalSamples
Definition: ImportAUP.cpp:200
std::vector< struct node > stack
Definition: ImportAUP.cpp:117
bool HandleNoteTrack(XMLTagHandler *&handle)
Definition: ImportAUP.cpp:862
bool SetWarning(const TranslatableString &msg)
Definition: ImportAUP.cpp:1662
void SetStreamUsage(wxInt32 WXUNUSED(StreamID), bool WXUNUSED(Use)) override
Definition: ImportAUP.cpp:499
bool HandleTimeTrack(XMLTagHandler *&handle)
Definition: ImportAUP.cpp:875
bool HandleControlPoint(XMLTagHandler *&handle)
Definition: ImportAUP.cpp:1051
bool HandleImport(XMLTagHandler *&handle)
Definition: ImportAUP.cpp:1320
bool HandleWaveClip(XMLTagHandler *&handle)
Definition: ImportAUP.cpp:995
bool HandleTag(XMLTagHandler *&handle)
Definition: ImportAUP.cpp:944
std::vector< fileinfo > mFiles
Definition: ImportAUP.cpp:199
bool HandleSimpleBlockFile(XMLTagHandler *&handle)
Definition: ImportAUP.cpp:1161
std::string mCurrentTag
Definition: ImportAUP.cpp:207
const TranslatableStrings & GetStreamInfo() override
Definition: ImportAUP.cpp:493
bool HandleTags(XMLTagHandler *&handle)
Definition: ImportAUP.cpp:908
bool AddSilence(sampleCount len)
Definition: ImportAUP.cpp:1413
bool HandleEnvelope(XMLTagHandler *&handle)
Definition: ImportAUP.cpp:1019
XMLTagHandler * HandleXMLChild(const std::string_view &tag) override
Definition: ImportAUP.cpp:537
void AddFile(sampleCount len, sampleFormat format, const FilePath &blockFilename=wxEmptyString, const FilePath &audioFilename=wxEmptyString, sampleCount origin=0, int channel=0)
Definition: ImportAUP.cpp:1391
AttributesList mAttrs
Definition: ImportAUP.cpp:208
void Import(ImportProgressListener &progressListener, WaveTrackFactory *trackFactory, TrackHolders &outTracks, Tags *tags) override
Definition: ImportAUP.cpp:309
An ImportPlugin for AUP files (pre-AUP3)
Definition: ImportAUP.cpp:70
TranslatableString GetPluginFormatDescription() override
Definition: ImportAUP.cpp:258
ImportHandle Open(const FilePath &fileName, AudacityProject *project) override
Definition: ImportAUP.cpp:263
wxString GetPluginStringID() override
Definition: ImportAUP.cpp:253
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.
static FormatterContext ProjectContext(const AudacityProject &project)
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
bool Import(const FilePath &fileName, bool addToHistory=true)
static ProjectFileManager & Get(AudacityProject &project)
static ProjectHistory & Get(AudacityProject &project)
static ProjectRate & Get(AudacityProject &project)
Definition: ProjectRate.cpp:28
void SetRate(double rate)
Definition: ProjectRate.cpp:58
static ProjectSelectionManager & Get(AudacityProject &project)
static ProjectSettings & Get(AudacityProject &project)
void SetSnapMode(SnapMode mode)
Definition: ProjectSnap.cpp:41
static ProjectSnap & Get(AudacityProject &project)
Definition: ProjectSnap.cpp:27
samplePtr ptr() const
Definition: SampleFormat.h:163
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:123
TrackKind * Add(const std::shared_ptr< TrackKind > &t)
Definition: Track.h:1195
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:354
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:103
XMLTagHandler * HandleXMLChild(const std::string_view &tag) override
Definition: WaveClip.cpp:611
double GetPlayEndTime() const override
Definition: WaveClip.cpp:1350
void InsertSilence(double t, double len, double *pEnvelopeValue=nullptr)
Definition: WaveClip.cpp:757
Envelope * GetEnvelope()
Definition: WaveClip.h:393
Used to create or clone a WaveTrack, with appropriate context from the project that will own the trac...
Definition: WaveTrack.h:1166
static WaveTrackFactory & Get(AudacityProject &project)
Definition: WaveTrack.cpp:4079
A Track that contains audio waveform data.
Definition: WaveTrack.h:220
void InsertSilence(double t, double len) override
Definition: WaveTrack.cpp:2142
WaveClip * CreateClip(double offset=.0, const wxString &name=wxEmptyString)
Create new clip and add it to this track.
Definition: WaveTrack.cpp:3424
bool IsLeader() const override
Definition: WaveTrack.cpp:2443
double GetEndTime() const override
Implement WideSampleSequence.
Definition: WaveTrack.cpp:2717
WaveClip * RightmostOrNewClip()
Get access to the last (rightmost) clip, or create a clip, if there is not already one.
Definition: WaveTrack.cpp:3450
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.
NUMERIC_FORMATS_API NumericFormatSymbol Lookup(const FormatterContext &context, const NumericConverterType &type, const NumericFormatSymbol &formatIdentifier)
Looks up the format, returns Default for the type if the format is not registered.
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:226
XMLTagHandler * handler
Definition: ImportAUP.cpp:115