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