39#include <wx/tokenzr.h>
50std::shared_ptr<ChannelInterval>
54 return std::make_shared<ChannelInterval>();
71 auto result =
tracks.Add(std::make_shared<LabelTrack>());
72 result->AttachedTrackObjects::BuildAll();
78 auto track = std::make_shared<LabelTrack>();
100 for (
auto &original: orig.
mLabels) {
126 auto pNewTrack = std::make_shared<LabelTrack>();
127 pNewTrack->Init(*
this);
128 pNewTrack->Paste(0.0, *
this);
140 if (index >= mLabels.size())
142 auto &
label = mLabels[index];
143 return std::make_shared<Interval>(
147std::shared_ptr<WideChannelGroupInterval>
155 if( iLabel >=
mLabels.size() ) {
169 const auto offset = origin -
mLabels[0].selectedRegion.t0();
170 for (
auto &labelStruct:
mLabels) {
171 labelStruct.selectedRegion.move(offset);
177 const std::optional<double>& oldTempo,
double newTempo)
180 if (!oldTempo.has_value())
182 const auto ratio = *oldTempo / newTempo;
184 label.selectedRegion.setTimes(
185 label.getT0() * ratio,
label.getT1() * ratio);
192 for (
size_t i = 0; i <
mLabels.size(); ++i) {
193 auto &labelStruct =
mLabels[i];
195 labelStruct.RegionRelation(b, e,
this);
197 labelStruct.selectedRegion.move(- (e-b));
203 labelStruct.selectedRegion.setTimes(
205 labelStruct.getT1() - (e - b));
207 labelStruct.selectedRegion.setT1(b);
209 labelStruct.selectedRegion.moveT1( - (e-b));
215bool LabelTrack::SplitDelete(
double b,
double e)
218 for (
size_t i = 0, len =
mLabels.size(); i < len; ++i) {
219 auto &labelStruct =
mLabels[i];
221 labelStruct.RegionRelation(b, e,
this);
227 labelStruct.selectedRegion.moveT1( - (e-b));
229 labelStruct.selectedRegion.setT0(e);
231 labelStruct.selectedRegion.setT1(b);
240 for (
auto &labelStruct:
mLabels) {
242 labelStruct.RegionRelation(pt, pt,
this);
245 labelStruct.selectedRegion.move(length);
247 labelStruct.selectedRegion.moveT1(length);
253 for (
auto &labelStruct:
mLabels) {
254 if (labelStruct.RegionRelation(b, e,
this) ==
257 double aux = b + (e - labelStruct.getT1());
258 labelStruct.selectedRegion.setTimes(
260 e - (labelStruct.getT0() - b));
268 for (
auto &labelStruct:
mLabels) {
269 labelStruct.selectedRegion.setTimes(
283 double shift = (e-b)*change - (e-b);
286 double shift = (t-b)*change - (t-b);
295 for (
auto &labelStruct:
mLabels) {
296 labelStruct.selectedRegion.setTimes(
297 warper.
Warp(labelStruct.getT0()),
298 warper.
Warp(labelStruct.getT1()));
307 const wxString& aTitle)
308: selectedRegion(region)
320 double t0,
double t1,
321 const wxString& aTitle)
322: selectedRegion(region)
342 this->SharedPointer<LabelTrack>(), {}, -1, -1 });
385 wxT(
"/FileFormats/LabelStyleChoice"),
399 S.StartStatic(
XO(
"Exported Label Style:"));
410 S.EndRadioButtonGroup();
425 static const wxString continuation{
wxT(
"\\") };
427 wxString firstLine = file.GetLine(index++);
433 wxStringTokenizer toker { firstLine,
wxT(
"\t") };
436 auto token = toker.GetNextToken();
442 token = toker.GetNextToken();
449 token = toker.GetNextToken();
467 while (index < (
int)file.GetLineCount() &&
468 file.GetLine(index).StartsWith(continuation))
471 if (index2 < index) {
472 wxStringTokenizer toker { file.GetLine(index2++),
wxT(
"\t") };
473 auto token = toker.GetNextToken();
474 if (token != continuation)
477 token = toker.GetNextToken();
482 token = toker.GetNextToken();
487 sr.setFrequencies(f0, f1);
495 file.AddLine(wxString::Format(
wxT(
"%s\t%s\t%s"),
511 file.AddLine(wxString::Format(
wxT(
"\\\t%s\t%s"),
520 double reg_t0,
double reg_t1,
const LabelTrack * WXUNUSED(parent))
const
523 bool retainLabels =
false;
525 wxASSERT(reg_t0 <= reg_t1);
534 if (reg_t0 < getT0() && reg_t1 > getT1())
535 return SURROUNDS_LABEL;
536 else if (reg_t1 < getT0())
538 else if (reg_t0 > getT1())
541 else if (reg_t0 >= getT0() && reg_t0 <= getT1() &&
542 reg_t1 >= getT0() && reg_t1 <= getT1())
545 else if (reg_t0 >= getT0() && reg_t0 <= getT1())
546 return BEGINS_IN_LABEL;
548 return ENDS_IN_LABEL;
562 if (reg_t0 <= getT0() && reg_t1 >= getT1())
563 return SURROUNDS_LABEL;
564 else if (reg_t1 <= getT0())
566 else if (reg_t0 >= getT1())
571 else if (reg_t0 > getT0() && reg_t0 < getT1() &&
572 reg_t1 > getT0() && reg_t1 < getT1())
577 else if (reg_t0 > getT0() && reg_t0 < getT1())
578 return BEGINS_IN_LABEL;
580 return ENDS_IN_LABEL;
589 for (
auto &labelStruct:
mLabels)
590 labelStruct.Export(f);
596 int lines = in.GetLineCount();
605 for (
int index = 0; index < lines;) {
620 if (tag ==
"label") {
627 for (
auto pair : attrs)
629 auto attr = pair.first;
630 auto value = pair.second;
635 else if (attr ==
"title")
636 title = value.ToWString();
652 else if (tag ==
"labeltrack") {
654 for (
auto pair : attrs)
656 auto attr = pair.first;
657 auto value = pair.second;
661 else if (attr ==
"numlabels" && value.TryGet(nValue))
665 wxLogWarning(
wxT(
"Project shows negative number of labels: %d"), nValue);
691 int len = mLabels.size();
693 xmlFile.StartTag(
wxT(
"labeltrack"));
695 xmlFile.WriteAttr(
wxT(
"numlabels"), len);
697 for (
auto &labelStruct: mLabels) {
698 xmlFile.StartTag(
wxT(
"label"));
699 labelStruct.getSelectedRegion()
700 .WriteXMLAttributes(xmlFile,
"t",
"t1");
702 xmlFile.WriteAttr(
wxT(
"title"), labelStruct.title);
703 xmlFile.EndTag(
wxT(
"label"));
706 xmlFile.EndTag(
wxT(
"labeltrack"));
712 auto tmp =
Copy(t0, t1);
724 if (!SplitDelete(t0, t1))
733 auto tmp = std::make_shared<LabelTrack>();
735 const auto lt =
static_cast<LabelTrack*
>(tmp.get());
737 for (
auto &labelStruct:
mLabels) {
739 labelStruct.RegionRelation(t0, t1,
this);
743 labelStruct.getT0() - t0,
744 labelStruct.getT1() - t0,
747 lt->mLabels.push_back(l);
756 lt->mLabels.push_back(l);
762 labelStruct.getT1() - t0,
765 lt->mLabels.push_back(l);
770 labelStruct.getT0() - t0,
774 lt->mLabels.push_back(l);
777 lt->mClipLen = (t1 - t0);
789 while (pos < len &&
mLabels[pos].getT0() < t)
792 for (
auto &labelStruct: sl.mLabels) {
795 labelStruct.getT0() + t,
796 labelStruct.getT1() + t,
815 double shiftAmt = lt.mClipLen > 0.0 ? lt.mClipLen : lt.GetEndTime();
832 if (n < 0 || t1 < t0)
835 double tLen = t1 - t0;
841 for (
unsigned int i = 0; i <
mLabels.size(); ++i)
844 mLabels[i].RegionRelation(t0, t1,
this);
849 unsigned int pos = i;
851 for (
int j = 1; j <= n; j++)
855 label.selectedRegion,
856 label.getT0() + j * tLen,
857 label.getT1() + j * tLen,
863 mLabels[pos].getT0() < l.getT0())
872 mLabels[i].selectedRegion.moveT1(n * tLen);
893 else if (newT1 < oldT1) {
905 for (
int i = 0; i < len; ++i) {
907 mLabels[i].RegionRelation(t0, t1,
this);
913 label.selectedRegion,
919 mLabels[i].selectedRegion.setT1(t0);
928 mLabels[i].selectedRegion.setT0(t1);
933 mLabels[i].selectedRegion.setT1(t0);
949 for (
auto &labelStruct:
mLabels) {
950 double t0 = labelStruct.getT0();
951 double t1 = labelStruct.getT1();
957 labelStruct.selectedRegion.setTimes(t0, t1);
972 const wxString &
title)
979 while (pos < len &&
mLabels[pos].getT0() < selectedRegion.
t0())
985 this->SharedPointer<LabelTrack>(),
title, -1, pos });
992 wxASSERT((index < (
int)
mLabels.size()));
993 auto iter =
mLabels.begin() + index;
994 const auto title = iter->title;
998 this->SharedPointer<LabelTrack>(),
title, index, -1 });
1008 const auto nn = (int)
mLabels.size();
1033 this->SharedPointer<LabelTrack>(),
mLabels[j].title, i, j });
1039 bool firstLabel =
true;
1042 for (
auto &labelStruct:
mLabels) {
1043 if (labelStruct.getT0() >= t0 &&
1044 labelStruct.getT1() <= t1)
1049 retVal += labelStruct.title;
1061 int len = (int)
mLabels.size();
1069 if (currentRegion.
t0() <
mLabels[len - 1].getT0()) {
1071 mLabels[i].getT0() <= currentRegion.
t0()) {
1087 int len = (int)
mLabels.size();
1095 if (currentRegion.
t0() >
mLabels[0].getT0()) {
1097 mLabels[i].getT0() >= currentRegion.
t0()) {
int AudacityMessageBox(const TranslatableString &message, const TranslatableString &caption, long style, wxWindow *parent, int x, int y)
const TranslatableString name
XXO("&Cut/Copy/Paste Toolbar")
static ProjectFileIORegistry::ObjectReaderEntry readerEntry
static const Track::TypeInfo & typeInfo()
audacity::BasicSettings * gPrefs
Contains declarations for TimeWarper, IdentityTimeWarper, ShiftTimeWarper, LinearTimeWarper,...
std::function< void(double)> ProgressReporter
std::shared_ptr< TrackList > TrackListHolder
std::vector< Attribute > AttributesList
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
double GetEndTime() const
Get the maximum of End() values of intervals, or 0 when none.
ComponentInterfaceSymbol pairs a persistent string identifier used internally with an optional,...
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)
TrackListHolder Copy(double t0, double t1, bool forClipboard=true) const override
Create new tracks and don't modify this track.
void ShiftLabelsOnInsert(double length, double pt)
void Paste(double t, const Track &src) override
Weak precondition allows overrides to replicate one channel into many.
void ScaleLabels(double b, double e, double change)
void InsertSilence(double t, double len) override
void WriteXML(XMLWriter &xmlFile) 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
std::shared_ptr< Interval > MakeInterval(size_t index)
int FindPrevLabel(const SelectedRegion ¤tSelection)
const LabelStruct * GetLabel(int index) const
size_t NIntervals() const override
Report the number of intervals.
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 DoOnProjectTempoChange(const std::optional< double > &oldTempo, double newTempo) override
void ChangeLabelsOnReverse(double b, double e)
bool PasteOver(double t, const Track &src)
XMLTagHandler * HandleXMLChild(const std::string_view &tag) override
TrackListHolder Cut(double t0, double t1) override
Create tracks and modify this track.
void Silence(double t0, double t1, ProgressReporter reportProgress={}) override
wxString GetTextOfLabels(double t0, double t1) const
Track::Holder PasteInto(AudacityProject &project, TrackList &list) const override
void Export(wxTextFile &f) const
Export labels including label start and end-times.
TrackListHolder Clone() const override
std::shared_ptr< WideChannelGroupInterval > DoGetInterval(size_t iInterval) override
Retrieve an interval.
void SetLabel(size_t iLabel, const LabelStruct &newLabel)
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)
void MoveTo(double dOffset) override
Change start time to given time point.
int AddLabel(const SelectedRegion ®ion, const wxString &title)
static wxString GetDefaultName()
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
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
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.
bool GetSelected() const
Selectedness is always the same for all channels of a group.
virtual void SetSelected(bool s)
static const TypeInfo & ClassTypeInfo()
R TypeSwitch(const Functions &...functions)
bool IsLeader() const override
std::shared_ptr< Track > Holder
bool HandleCommonXMLAttribute(const std::string_view &attr, const XMLAttributeValueView &valueView)
void WriteCommonXMLAttributes(XMLWriter &xmlFile, bool includeNameAndSelected=true) const
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)
static TrackListHolder Temporary(AudacityProject *pProject, const Track::Holder &left={}, const Track::Holder &right={})
Generates overrides of channel-related functions.
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...
virtual bool Read(const wxString &key, bool *value) const =0
auto begin(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
static EnumSetting< bool > LabelStyleSetting
void AddControls(ShuttleGui &S)
ImportExportPrefs::RegisteredControls reg
void rotate(const float *oldPhase, const float *newPhase, std::complex< float > *dst, int32_t n)
std::shared_ptr< ChannelInterval > DoGetChannel(size_t iChannel) override
Retrieve a channel.
Empty argument passed to some public constructors.