39#include <wx/tokenzr.h>
66 auto result = tracks.Add(std::make_shared<LabelTrack>());
67 result->AttachedTrackObjects::BuildAll();
73 auto track = std::make_shared<LabelTrack>();
95 for (
auto &original: orig.
mLabels) {
120 auto pNewTrack = std::make_shared<LabelTrack>();
121 pNewTrack->Init(*
this);
122 pNewTrack->Paste(0.0,
this);
126template<
typename IntervalType>
131 std::make_unique<LabelTrack::IntervalData>( index ) };
136 return DoMakeInterval<ConstInterval>(mLabels[index], index);
141 return DoMakeInterval<Interval>(mLabels[index], index);
144template<
typename Container,
typename LabelTrack >
148 for (
size_t ii = 0, nn = track.
GetNumLabels(); ii < nn; ++ii)
155 return DoMakeIntervals<ConstIntervals>(*
this);
160 return DoMakeIntervals<Intervals>(*
this);
165 if( iLabel >=
mLabels.size() ) {
178 for (
auto &labelStruct:
mLabels)
179 labelStruct.selectedRegion.move(dOffset);
185 for (
size_t i = 0; i <
mLabels.size(); ++i) {
186 auto &labelStruct =
mLabels[i];
188 labelStruct.RegionRelation(b, e,
this);
190 labelStruct.selectedRegion.move(- (e-b));
196 labelStruct.selectedRegion.setTimes(
198 labelStruct.getT1() - (e - b));
200 labelStruct.selectedRegion.setT1(b);
202 labelStruct.selectedRegion.moveT1( - (e-b));
208bool LabelTrack::SplitDelete(
double b,
double e)
211 for (
size_t i = 0, len =
mLabels.size(); i < len; ++i) {
212 auto &labelStruct =
mLabels[i];
214 labelStruct.RegionRelation(b, e,
this);
220 labelStruct.selectedRegion.moveT1( - (e-b));
222 labelStruct.selectedRegion.setT0(e);
224 labelStruct.selectedRegion.setT1(b);
233 for (
auto &labelStruct:
mLabels) {
235 labelStruct.RegionRelation(pt, pt,
this);
238 labelStruct.selectedRegion.move(length);
240 labelStruct.selectedRegion.moveT1(length);
246 for (
auto &labelStruct:
mLabels) {
247 if (labelStruct.RegionRelation(b, e,
this) ==
250 double aux = b + (e - labelStruct.getT1());
251 labelStruct.selectedRegion.setTimes(
253 e - (labelStruct.getT0() - b));
261 for (
auto &labelStruct:
mLabels) {
262 labelStruct.selectedRegion.setTimes(
276 double shift = (e-b)*change - (e-b);
279 double shift = (t-b)*change - (t-b);
288 for (
auto &labelStruct:
mLabels) {
289 labelStruct.selectedRegion.setTimes(
290 warper.
Warp(labelStruct.getT0()),
291 warper.
Warp(labelStruct.getT1()));
300 const wxString& aTitle)
301: selectedRegion(region)
313 double t0,
double t1,
314 const wxString& aTitle)
315: selectedRegion(region)
335 EVT_LABELTRACK_SELECTION, SharedPointer<LabelTrack>(), {}, -1, -1
362 for (
auto &labelStruct:
mLabels) {
363 const double t1 = labelStruct.getT1();
372 return std::make_shared<LabelTrack>( *
this );
406 static const wxString continuation{ wxT(
"\\") };
408 wxString firstLine = file.GetLine(index++);
414 wxStringTokenizer toker { firstLine, wxT(
"\t") };
417 auto token = toker.GetNextToken();
423 token = toker.GetNextToken();
430 token = toker.GetNextToken();
448 while (index < (
int)file.GetLineCount() &&
449 file.GetLine(index).StartsWith(continuation))
452 if (index2 < index) {
453 wxStringTokenizer toker { file.GetLine(index2++), wxT(
"\t") };
454 auto token = toker.GetNextToken();
455 if (token != continuation)
458 token = toker.GetNextToken();
463 token = toker.GetNextToken();
468 sr.setFrequencies(f0, f1);
476 file.AddLine(wxString::Format(wxT(
"%s\t%s\t%s"),
492 file.AddLine(wxString::Format(wxT(
"\\\t%s\t%s"),
501 double reg_t0,
double reg_t1,
const LabelTrack * WXUNUSED(parent))
const
504 bool retainLabels =
false;
506 wxASSERT(reg_t0 <= reg_t1);
507 gPrefs->Read(wxT(
"/GUI/RetainLabels"), &retainLabels);
515 if (reg_t0 < getT0() && reg_t1 > getT1())
516 return SURROUNDS_LABEL;
517 else if (reg_t1 < getT0())
519 else if (reg_t0 > getT1())
522 else if (reg_t0 >= getT0() && reg_t0 <= getT1() &&
523 reg_t1 >= getT0() && reg_t1 <= getT1())
526 else if (reg_t0 >= getT0() && reg_t0 <= getT1())
527 return BEGINS_IN_LABEL;
529 return ENDS_IN_LABEL;
543 if (reg_t0 <= getT0() && reg_t1 >= getT1())
544 return SURROUNDS_LABEL;
545 else if (reg_t1 <= getT0())
547 else if (reg_t0 >= getT1())
552 else if (reg_t0 > getT0() && reg_t0 < getT1() &&
553 reg_t1 > getT0() && reg_t1 < getT1())
558 else if (reg_t0 > getT0() && reg_t0 < getT1())
559 return BEGINS_IN_LABEL;
561 return ENDS_IN_LABEL;
570 for (
auto &labelStruct:
mLabels)
571 labelStruct.Export(f);
577 int lines = in.GetLineCount();
586 for (
int index = 0; index < lines;) {
601 if (tag ==
"label") {
608 for (
auto pair : attrs)
610 auto attr = pair.first;
611 auto value = pair.second;
616 else if (attr ==
"title")
617 title = value.ToWString();
633 else if (tag ==
"labeltrack") {
635 for (
auto pair : attrs)
637 auto attr = pair.first;
638 auto value = pair.second;
642 else if (attr ==
"numlabels" && value.TryGet(nValue))
646 wxLogWarning(wxT(
"Project shows negative number of labels: %d"), nValue);
671 int len = mLabels.size();
673 xmlFile.StartTag(wxT(
"labeltrack"));
675 xmlFile.WriteAttr(wxT(
"numlabels"), len);
677 for (
auto &labelStruct: mLabels) {
678 xmlFile.StartTag(wxT(
"label"));
679 labelStruct.getSelectedRegion()
680 .WriteXMLAttributes(xmlFile,
"t",
"t1");
682 xmlFile.WriteAttr(wxT(
"title"), labelStruct.title);
683 xmlFile.EndTag(wxT(
"label"));
686 xmlFile.EndTag(wxT(
"labeltrack"));
691 auto tmp =
Copy(t0, t1);
705 if (!SplitDelete(t0, t1))
714 auto tmp = std::make_shared<LabelTrack>();
716 const auto lt =
static_cast<LabelTrack*
>(tmp.get());
718 for (
auto &labelStruct:
mLabels) {
720 labelStruct.RegionRelation(t0, t1,
this);
724 labelStruct.getT0() - t0,
725 labelStruct.getT1() - t0,
728 lt->mLabels.push_back(l);
737 lt->mLabels.push_back(l);
743 labelStruct.getT1() - t0,
746 lt->mLabels.push_back(l);
751 labelStruct.getT0() - t0,
755 lt->mLabels.push_back(l);
758 lt->mClipLen = (t1 - t0);
770 while (pos < len &&
mLabels[pos].getT0() < t)
773 for (
auto &labelStruct: sl->mLabels) {
776 labelStruct.getT0() + t,
777 labelStruct.getT1() + t,
796 double shiftAmt = lt->mClipLen > 0.0 ? lt->mClipLen : lt->GetEndTime();
813 if (n < 0 || t1 < t0)
816 double tLen = t1 - t0;
822 for (
unsigned int i = 0; i <
mLabels.size(); ++i)
825 mLabels[i].RegionRelation(t0, t1,
this);
830 unsigned int pos = i;
832 for (
int j = 1; j <= n; j++)
836 label.selectedRegion,
837 label.getT0() + j * tLen,
838 label.getT1() + j * tLen,
844 mLabels[pos].getT0() < l.getT0())
853 mLabels[i].selectedRegion.moveT1(n * tLen);
873 else if (newT1 < oldT1) {
885 for (
int i = 0; i < len; ++i) {
887 mLabels[i].RegionRelation(t0, t1,
this);
893 label.selectedRegion,
899 mLabels[i].selectedRegion.setT1(t0);
908 mLabels[i].selectedRegion.setT0(t1);
913 mLabels[i].selectedRegion.setT1(t0);
928 for (
auto &labelStruct:
mLabels) {
929 double t0 = labelStruct.getT0();
930 double t1 = labelStruct.getT1();
936 labelStruct.selectedRegion.setTimes(t0, t1);
951 const wxString &
title)
958 while (pos < len &&
mLabels[pos].getT0() < selectedRegion.
t0())
964 EVT_LABELTRACK_ADDITION, SharedPointer<LabelTrack>(),
title, -1, pos
973 wxASSERT((index < (
int)
mLabels.size()));
974 auto iter =
mLabels.begin() + index;
975 const auto title = iter->title;
979 EVT_LABELTRACK_DELETION, SharedPointer<LabelTrack>(),
title, index, -1
991 const auto nn = (int)
mLabels.size();
1016 EVT_LABELTRACK_PERMUTED, SharedPointer<LabelTrack>(),
1019 ProcessEvent( evt );
1025 bool firstLabel =
true;
1028 for (
auto &labelStruct:
mLabels) {
1029 if (labelStruct.getT0() >= t0 &&
1030 labelStruct.getT1() <= t1)
1035 retVal += labelStruct.title;
1047 int len = (int)
mLabels.size();
1055 if (currentRegion.
t0() <
mLabels[len - 1].getT0()) {
1057 mLabels[i].getT0() <= currentRegion.
t0()) {
1073 int len = (int)
mLabels.size();
1081 if (currentRegion.
t0() >
mLabels[0].getT0()) {
1083 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)
wxDEFINE_EVENT(EVT_LABELTRACK_ADDITION, LabelTrackEvent)
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()
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, if Traits<Type>::iterated_type is defined.
auto begin(const Ptr< Type, BaseDeleter > &p)
Enables range-for, if Traits<Type>::iterated_type is defined.