39#include <wx/tokenzr.h>
61 auto result = tracks.Add(std::make_shared<LabelTrack>());
62 result->AttachedTrackObjects::BuildAll();
68 auto track = std::make_shared<LabelTrack>();
90 for (
auto &original: orig.
mLabels) {
115 auto pNewTrack = std::make_shared<LabelTrack>();
116 pNewTrack->Init(*
this);
117 pNewTrack->Paste(0.0,
this);
121template<
typename IntervalType>
126 std::make_unique<LabelTrack::IntervalData>( index ) };
131 return DoMakeInterval<ConstInterval>(mLabels[index], index);
136 return DoMakeInterval<Interval>(mLabels[index], index);
139template<
typename Container,
typename LabelTrack >
143 for (
size_t ii = 0, nn = track.
GetNumLabels(); ii < nn; ++ii)
150 return DoMakeIntervals<ConstIntervals>(*
this);
155 return DoMakeIntervals<Intervals>(*
this);
160 if( iLabel >=
mLabels.size() ) {
173 for (
auto &labelStruct:
mLabels)
174 labelStruct.selectedRegion.move(dOffset);
180 for (
size_t i = 0; i <
mLabels.size(); ++i) {
181 auto &labelStruct =
mLabels[i];
183 labelStruct.RegionRelation(b, e,
this);
185 labelStruct.selectedRegion.move(- (e-b));
191 labelStruct.selectedRegion.setTimes(
193 labelStruct.getT1() - (e - b));
195 labelStruct.selectedRegion.setT1(b);
197 labelStruct.selectedRegion.moveT1( - (e-b));
203bool LabelTrack::SplitDelete(
double b,
double e)
206 for (
size_t i = 0, len =
mLabels.size(); i < len; ++i) {
207 auto &labelStruct =
mLabels[i];
209 labelStruct.RegionRelation(b, e,
this);
215 labelStruct.selectedRegion.moveT1( - (e-b));
217 labelStruct.selectedRegion.setT0(e);
219 labelStruct.selectedRegion.setT1(b);
228 for (
auto &labelStruct:
mLabels) {
230 labelStruct.RegionRelation(pt, pt,
this);
233 labelStruct.selectedRegion.move(length);
235 labelStruct.selectedRegion.moveT1(length);
241 for (
auto &labelStruct:
mLabels) {
242 if (labelStruct.RegionRelation(b, e,
this) ==
245 double aux = b + (e - labelStruct.getT1());
246 labelStruct.selectedRegion.setTimes(
248 e - (labelStruct.getT0() - b));
256 for (
auto &labelStruct:
mLabels) {
257 labelStruct.selectedRegion.setTimes(
271 double shift = (e-b)*change - (e-b);
274 double shift = (t-b)*change - (t-b);
283 for (
auto &labelStruct:
mLabels) {
284 labelStruct.selectedRegion.setTimes(
285 warper.
Warp(labelStruct.getT0()),
286 warper.
Warp(labelStruct.getT1()));
295 const wxString& aTitle)
296: selectedRegion(region)
308 double t0,
double t1,
309 const wxString& aTitle)
310: selectedRegion(region)
330 this->SharedPointer<LabelTrack>(), {}, -1, -1 });
354 for (
auto &labelStruct:
mLabels) {
355 const double t1 = labelStruct.getT1();
400 static const wxString continuation{
wxT(
"\\") };
402 wxString firstLine = file.GetLine(index++);
408 wxStringTokenizer toker { firstLine,
wxT(
"\t") };
411 auto token = toker.GetNextToken();
417 token = toker.GetNextToken();
424 token = toker.GetNextToken();
442 while (index < (
int)file.GetLineCount() &&
443 file.GetLine(index).StartsWith(continuation))
446 if (index2 < index) {
447 wxStringTokenizer toker { file.GetLine(index2++),
wxT(
"\t") };
448 auto token = toker.GetNextToken();
449 if (token != continuation)
452 token = toker.GetNextToken();
457 token = toker.GetNextToken();
462 sr.setFrequencies(f0, f1);
470 file.AddLine(wxString::Format(
wxT(
"%s\t%s\t%s"),
486 file.AddLine(wxString::Format(
wxT(
"\\\t%s\t%s"),
495 double reg_t0,
double reg_t1,
const LabelTrack * WXUNUSED(parent))
const
498 bool retainLabels =
false;
500 wxASSERT(reg_t0 <= reg_t1);
501 gPrefs->Read(
wxT(
"/GUI/RetainLabels"), &retainLabels);
509 if (reg_t0 < getT0() && reg_t1 > getT1())
510 return SURROUNDS_LABEL;
511 else if (reg_t1 < getT0())
513 else if (reg_t0 > getT1())
516 else if (reg_t0 >= getT0() && reg_t0 <= getT1() &&
517 reg_t1 >= getT0() && reg_t1 <= getT1())
520 else if (reg_t0 >= getT0() && reg_t0 <= getT1())
521 return BEGINS_IN_LABEL;
523 return ENDS_IN_LABEL;
537 if (reg_t0 <= getT0() && reg_t1 >= getT1())
538 return SURROUNDS_LABEL;
539 else if (reg_t1 <= getT0())
541 else if (reg_t0 >= getT1())
546 else if (reg_t0 > getT0() && reg_t0 < getT1() &&
547 reg_t1 > getT0() && reg_t1 < getT1())
552 else if (reg_t0 > getT0() && reg_t0 < getT1())
553 return BEGINS_IN_LABEL;
555 return ENDS_IN_LABEL;
564 for (
auto &labelStruct:
mLabels)
565 labelStruct.Export(f);
571 int lines = in.GetLineCount();
580 for (
int index = 0; index < lines;) {
595 if (tag ==
"label") {
602 for (
auto pair : attrs)
604 auto attr = pair.first;
605 auto value = pair.second;
610 else if (attr ==
"title")
611 title = value.ToWString();
627 else if (tag ==
"labeltrack") {
629 for (
auto pair : attrs)
631 auto attr = pair.first;
632 auto value = pair.second;
636 else if (attr ==
"numlabels" && value.TryGet(nValue))
640 wxLogWarning(
wxT(
"Project shows negative number of labels: %d"), nValue);
665 int len = mLabels.size();
667 xmlFile.StartTag(
wxT(
"labeltrack"));
669 xmlFile.WriteAttr(
wxT(
"numlabels"), len);
671 for (
auto &labelStruct: mLabels) {
672 xmlFile.StartTag(
wxT(
"label"));
673 labelStruct.getSelectedRegion()
674 .WriteXMLAttributes(xmlFile,
"t",
"t1");
676 xmlFile.WriteAttr(
wxT(
"title"), labelStruct.title);
677 xmlFile.EndTag(
wxT(
"label"));
680 xmlFile.EndTag(
wxT(
"labeltrack"));
685 auto tmp =
Copy(t0, t1);
699 if (!SplitDelete(t0, t1))
708 auto tmp = std::make_shared<LabelTrack>();
710 const auto lt =
static_cast<LabelTrack*
>(tmp.get());
712 for (
auto &labelStruct:
mLabels) {
714 labelStruct.RegionRelation(t0, t1,
this);
718 labelStruct.getT0() - t0,
719 labelStruct.getT1() - t0,
722 lt->mLabels.push_back(l);
731 lt->mLabels.push_back(l);
737 labelStruct.getT1() - t0,
740 lt->mLabels.push_back(l);
745 labelStruct.getT0() - t0,
749 lt->mLabels.push_back(l);
752 lt->mClipLen = (t1 - t0);
764 while (pos < len &&
mLabels[pos].getT0() < t)
767 for (
auto &labelStruct: sl->mLabels) {
770 labelStruct.getT0() + t,
771 labelStruct.getT1() + t,
790 double shiftAmt = lt->mClipLen > 0.0 ? lt->mClipLen : lt->GetEndTime();
807 if (n < 0 || t1 < t0)
810 double tLen = t1 - t0;
816 for (
unsigned int i = 0; i <
mLabels.size(); ++i)
819 mLabels[i].RegionRelation(t0, t1,
this);
824 unsigned int pos = i;
826 for (
int j = 1; j <= n; j++)
830 label.selectedRegion,
831 label.getT0() + j * tLen,
832 label.getT1() + j * tLen,
838 mLabels[pos].getT0() < l.getT0())
847 mLabels[i].selectedRegion.moveT1(n * tLen);
867 else if (newT1 < oldT1) {
879 for (
int i = 0; i < len; ++i) {
881 mLabels[i].RegionRelation(t0, t1,
this);
887 label.selectedRegion,
893 mLabels[i].selectedRegion.setT1(t0);
902 mLabels[i].selectedRegion.setT0(t1);
907 mLabels[i].selectedRegion.setT1(t0);
922 for (
auto &labelStruct:
mLabels) {
923 double t0 = labelStruct.getT0();
924 double t1 = labelStruct.getT1();
930 labelStruct.selectedRegion.setTimes(t0, t1);
945 const wxString &
title)
952 while (pos < len &&
mLabels[pos].getT0() < selectedRegion.
t0())
958 this->SharedPointer<LabelTrack>(),
title, -1, pos });
965 wxASSERT((index < (
int)
mLabels.size()));
966 auto iter =
mLabels.begin() + index;
967 const auto title = iter->title;
971 this->SharedPointer<LabelTrack>(),
title, index, -1 });
981 const auto nn = (int)
mLabels.size();
1006 this->SharedPointer<LabelTrack>(),
mLabels[j].title, i, j });
1012 bool firstLabel =
true;
1015 for (
auto &labelStruct:
mLabels) {
1016 if (labelStruct.getT0() >= t0 &&
1017 labelStruct.getT1() <= t1)
1022 retVal += labelStruct.title;
1034 int len = (int)
mLabels.size();
1042 if (currentRegion.
t0() <
mLabels[len - 1].getT0()) {
1044 mLabels[i].getT0() <= currentRegion.
t0()) {
1060 int len = (int)
mLabels.size();
1068 if (currentRegion.
t0() >
mLabels[0].getT0()) {
1070 mLabels[i].getT0() >= currentRegion.
t0()) {
int AudacityMessageBox(const TranslatableString &message, const TranslatableString &caption, long style, wxWindow *parent, int x, int y)
const TranslatableString name
static ProjectFileIORegistry::ObjectReaderEntry readerEntry
static Container DoMakeIntervals(LabelTrack &track)
static IntervalType DoMakeInterval(const LabelStruct &label, size_t index)
static const Track::TypeInfo & typeInfo()
Contains declarations for TimeWarper, IdentityTimeWarper, ShiftTimeWarper, LinearTimeWarper,...
std::vector< Attribute > AttributesList
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
A start and an end time, and non-mutative access to optional extra information.
static EnumSetting< bool > LabelStyleSetting
static wxString ToString(double numberToConvert, int digitsAfterDecimalPoint=-1)
Convert a number to a string, always uses the dot as decimal separator.
static bool CompatibleToDouble(const wxString &stringToConvert, double *result)
Convert a string to a number.
A LabelStruct holds information for ONE label in a LabelTrack.
void MoveLabel(int iEdge, double fNewTime)
int x1
Pixel position of left hand glyph.
int x
width of the text in pixels.
TimeRelations
Relationships between selection region and labels.
static LabelStruct Import(wxTextFile &file, int &index)
void Export(wxTextFile &file) const
TimeRelations RegionRelation(double reg_t0, double reg_t1, const LabelTrack *parent=NULL) const
SelectedRegion selectedRegion
bool AdjustEdge(int iEdge, double fNewTime)
double getDuration() const
bool updated
Pixel position of label.
int width
Text of the label.
int xText
Pixel position of right hand glyph.
int y
Pixel position of left hand side of text box.
A LabelTrack is a Track that holds labels (LabelStruct).
bool HandleXMLTag(const std::string_view &tag, const AttributesList &attrs) override
bool Repeat(double t0, double t1, int n)
void ShiftLabelsOnInsert(double length, double pt)
void ScaleLabels(double b, double e, double change)
void InsertSilence(double t, double len) override
void WriteXML(XMLWriter &xmlFile) const override
double GetStartTime() const override
void SyncLockAdjust(double oldT1, double newT1) override
void Import(wxTextFile &f)
Import labels, handling files with or without end-times.
const TypeInfo & GetTypeInfo() const override
ConstIntervals GetIntervals() const override
Report times on the track where important intervals begin and end, for UI to snap to.
int FindPrevLabel(const SelectedRegion ¤tSelection)
double GetOffset() const override
void Paste(double t, const Track *src) override
const LabelStruct * GetLabel(int index) const
void DeleteLabel(int index)
int FindNextLabel(const SelectedRegion ¤tSelection)
void SetSelected(bool s) override
static LabelTrack * New(AudacityProject &project)
void WarpLabels(const TimeWarper &warper)
void ChangeLabelsOnReverse(double b, double e)
Track::Holder Copy(double t0, double t1, bool forClipboard=true) const override
ConstInterval MakeInterval(size_t index) const
XMLTagHandler * HandleXMLChild(const std::string_view &tag) override
void Silence(double t0, double t1) override
Track::Holder Cut(double t0, double t1) override
wxString GetTextOfLabels(double t0, double t1) const
void Export(wxTextFile &f) const
Export labels including label start and end-times.
Track::Holder Clone() const override
void SetLabel(size_t iLabel, const LabelStruct &newLabel)
double GetEndTime() const override
void SetOffset(double dOffset) override
static LabelTrack * Create(TrackList &trackList, const wxString &name)
Create a new LabelTrack with specified name and append it to the trackList.
void Clear(double t0, double t1) override
double AdjustTimeStampOnScale(double t, double b, double e, double change)
int AddLabel(const SelectedRegion ®ion, const wxString &title)
bool PasteOver(double t, const Track *src)
static wxString GetDefaultName()
Track::Holder PasteInto(AudacityProject &) const override
Find or create the destination track for a paste, maybe in a different project.
static const TypeInfo & ClassTypeInfo()
CallbackReturn Publish(const struct LabelTrackEvent &message)
Send a message to connected callbacks.
Defines a selected portion of a project.
bool setTimes(double t0, double t1)
bool HandleXMLAttribute(const std::string_view &attr, const XMLAttributeValueView &value, const char *legacyT0Name=sDefaultT0Name, const char *legacyT1Name=sDefaultT1Name)
bool setT0(double t, bool maySwap=true)
bool setT1(double t, bool maySwap=true)
static const int UndefinedFrequency
Transforms one point in time to another point. For example, a time stretching effect might use one to...
virtual double Warp(double originalTime) const =0
Abstract base class for an object holding data associated with points on a time axis.
virtual void SetSelected(bool s)
static const TypeInfo & ClassTypeInfo()
R TypeSwitch(const Functions &...functions)
Use this function rather than testing track type explicitly and making down-casts.
std::shared_ptr< Track > Holder
bool HandleCommonXMLAttribute(const std::string_view &attr, const XMLAttributeValueView &valueView)
void WriteCommonXMLAttributes(XMLWriter &xmlFile, bool includeNameAndSelected=true) const
std::vector< Interval > Intervals
std::vector< ConstInterval > ConstIntervals
A start and an end time, and mutative access to optional extra information.
A flat linked list of tracks supporting Add, Remove, Clear, and Contains, serialization of the list o...
wxString MakeUniqueTrackName(const wxString &baseTrackName) const
Returns string that contains baseTrackName, but is guaranteed to be unique among other tracks in that...
TrackKind * Add(const std::shared_ptr< TrackKind > &t)
static TrackList & Get(AudacityProject &project)
This class is an interface which should be implemented by classes which wish to be able to load and s...
Base class for XMLFileWriter and XMLStringWriter that provides the general functionality for creating...
auto end(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
auto begin(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
Empty argument passed to some public constructors.