Update of /cvsroot/audacity/audacity-src/src In directory 23jxhf1.ch3.sourceforge.com:/tmp/cvs-serv20133
Modified Files: LabelTrack.cpp LabelTrack.h Menus.cpp WaveClip.cpp WaveClip.h WaveTrack.cpp Log Message: Al Dimond's patch for Repeating Labels with track linking on, covering some other bugs as well. Index: WaveClip.cpp =================================================================== RCS file: /cvsroot/audacity/audacity-src/src/WaveClip.cpp,v retrieving revision 1.57 retrieving revision 1.58 diff -u -d -r1.57 -r1.58 --- WaveClip.cpp 9 Oct 2009 14:28:48 -0000 1.57 +++ WaveClip.cpp 18 Oct 2009 19:58:17 -0000 1.58 @@ -308,6 +308,7 @@ mAppendBuffer = NULL; mAppendBufferLen = 0; mDirty = 0; + mIsPlaceholder = false; } WaveClip::WaveClip(WaveClip& orig, DirManager *projDirManager) @@ -339,6 +340,7 @@ mAppendBuffer = NULL; mAppendBufferLen = 0; mDirty = 0; + mIsPlaceholder = orig.GetIsPlaceholder(); } WaveClip::~WaveClip() Index: LabelTrack.h =================================================================== RCS file: /cvsroot/audacity/audacity-src/src/LabelTrack.h,v retrieving revision 1.51 retrieving revision 1.52 diff -u -d -r1.51 -r1.52 --- LabelTrack.h 12 Sep 2009 06:05:41 -0000 1.51 +++ LabelTrack.h 18 Oct 2009 19:58:17 -0000 1.52 @@ -117,6 +117,7 @@ virtual bool Copy (double t0, double t1, Track ** dest);// const; virtual bool Clear(double t0, double t1); virtual bool Paste(double t, Track * src); + bool Repeat(double t0, double t1, int n); virtual bool Silence(double t0, double t1); virtual bool InsertSilence(double t, double len); Index: WaveClip.h =================================================================== RCS file: /cvsroot/audacity/audacity-src/src/WaveClip.h,v retrieving revision 1.40 retrieving revision 1.41 diff -u -d -r1.40 -r1.41 --- WaveClip.h 9 Oct 2009 14:28:48 -0000 1.40 +++ WaveClip.h 18 Oct 2009 19:58:17 -0000 1.41 @@ -213,6 +213,10 @@ // Cache of values to colour pixels of Spectrogram - used by TrackArtist SpecPxCache *mSpecPxCache; + // AWD, Oct 2009: for pasting whitespace at the end of selection + bool GetIsPlaceholder() { return mIsPlaceholder; }; + void SetIsPlaceholder(bool val) { mIsPlaceholder = val; }; + protected: wxRect mDisplayRect; @@ -239,6 +243,9 @@ // Cut Lines are nothing more than ordinary wave clips, with the // offset relative to the start of the clip. WaveClipList mCutLines; + + // AWD, Oct. 2009: for whitespace-at-end-of-selection pasting + bool mIsPlaceholder; }; #endif Index: LabelTrack.cpp =================================================================== RCS file: /cvsroot/audacity/audacity-src/src/LabelTrack.cpp,v retrieving revision 1.118 retrieving revision 1.119 diff -u -d -r1.118 -r1.119 --- LabelTrack.cpp 29 Sep 2009 00:28:07 -0000 1.118 +++ LabelTrack.cpp 18 Oct 2009 19:58:16 -0000 1.119 @@ -278,14 +278,14 @@ { for (unsigned int i=0;i<mLabels.GetCount();i++){ // label is after the insert point - if (mLabels[i]->t > pt) { + if (mLabels[i]->t >= pt) { mLabels[i]->t = mLabels[i]->t + length; mLabels[i]->t1 = mLabels[i]->t1 + length; // label is before the insert point - }else if (mLabels[i]->t1 < pt) { + }else if (mLabels[i]->t1 <= pt) { //nothing // insert point is inside the label - }else if (mLabels[i]->t < pt && mLabels[i]->t1 > pt){ + }else{ mLabels[i]->t1 = mLabels[i]->t1 + length; } } @@ -2176,6 +2176,54 @@ return true; } +// This repeats the labels in a time interval a specified number of times. +// Like Paste(), it does not shift existing labels over +// - It assumes that you've already called ShiftLabelsOnInsert(), because +// sometimes with linking enabled that's hard to avoid. +// - It assumes that you inserted the necessary extra time at t1, not t0. +bool LabelTrack::Repeat(double t0, double t1, int n) +{ + // Sanity-check the arguments + if (n < 0 || t1 < t0) return false; + + double tLen = t1 - t0; + + for (unsigned int i = 0; i < mLabels.GetCount(); i++) + { + if (mLabels[i]->t >= t0 && mLabels[i]->t <= t1 && + mLabels[i]->t1 >= t0 && mLabels[i]->t1 <= t1) + { + // Label is completely inside the selection; duplicate it in each + // repeat interval + unsigned int pos = i; // running label insertion position in mLabels + + for (int j = 1; j <= n; j++) + { + LabelStruct *l = new LabelStruct(); + l->t = mLabels[i]->t + j * tLen; + l->t1 = mLabels[i]->t1 + j * tLen; + l->title = mLabels[i]->title; + + // Figure out where to insert + while (pos < mLabels.Count() && mLabels[pos]->t < l->t) + pos++; + mLabels.Insert(l, pos); + } + } + else if (mLabels[i]->t < t0 && + mLabels[i]->t1 >= t0 && mLabels[i]->t1 <= t1) + { + // Label ends inside the selection; ShiftLabelsOnInsert() hasn't touched + // it, and we need to extend it through to the last repeat interval + mLabels[i]->t1 += n * tLen; + } + + // Other cases have already been handled by ShiftLabelsOnInsert() + } + + return true; +} + bool LabelTrack::Clear(double t0, double t1) { AudacityProject *p = GetActiveProject(); Index: WaveTrack.cpp =================================================================== RCS file: /cvsroot/audacity/audacity-src/src/WaveTrack.cpp,v retrieving revision 1.169 retrieving revision 1.170 diff -u -d -r1.169 -r1.170 --- WaveTrack.cpp 11 Oct 2009 14:55:47 -0000 1.169 +++ WaveTrack.cpp 18 Oct 2009 19:58:17 -0000 1.170 @@ -438,6 +438,25 @@ } } } + + // AWD, Oct 2009: If the selection ends in whitespace, create a placeholder + // clip representing that whitespace + if (newTrack->GetEndTime() + 1.0 / newTrack->GetRate() < t1 - t0) + { + WaveClip *placeholder = new WaveClip(mDirManager, + newTrack->GetSampleFormat(), newTrack->GetRate()); + placeholder->SetIsPlaceholder(true); + if ( ! placeholder->InsertSilence( + 0, (t1 - t0) - newTrack->GetEndTime()) ) + { + delete placeholder; + } + else + { + placeholder->Offset(newTrack->GetEndTime()); + newTrack->mClips.Append(placeholder); + } + } *dest = newTrack; @@ -518,7 +537,10 @@ // If duration is 0, then it's just a plain paste if (dur == 0.0) { - return Paste(t0, src, tracks, relativeLabels); + if (useHandlePaste) + return HandlePaste(t0, src); + else + return Paste(t0, src, tracks, relativeLabels); } // If provided time warper was NULL, use a default one that does nothing @@ -863,38 +885,74 @@ // the present track is in a project with groups but doesn't belong to any of them return HandlePaste(t0, src); + // False return from this function causes its changes to not be pushed to + // the undo stack. So we paste into this track first, so any failure + // (usually from "clips can't move" mode) comes before other changes. + // Failures to paste to the group tracks should not cause this function to + // return false; the result might be OK with the user, and if not he can + // easily undo it + if (!HandlePaste(t0, src)) + { + return false; + } + for( ; t; t = it.Next() ) { if (t->GetKind() == Track::Wave) { + WaveTrack *wt = (WaveTrack *)t; if (t==this) { - //paste in the track - if ( !( ((WaveTrack *)t)->HandlePaste(t0, src)) ) return false; + // This track has already been pasted; if it's a stereo track skip + // over the other channel as well. if (t->GetLinked()) t=it.Next(); } else { if (! (t->GetSelected()) ) { if ( sel_len > length ) - // if selection is bigger than the content to add then we need to clear the extra length in the group tracks - ((WaveTrack*)t)->HandleClear(t0+length, t0+sel_len, false, false); + // if selection is bigger than the content to add then we + // need to clear the extra length in the group tracks + wt->HandleClear(t0+length, t0+sel_len, false, false); else if (sel_len < length) { - // if selection is smaller than the content to add then we need to add extra silence in the group tracks - TrackFactory *factory = p->GetTrackFactory(); - WaveTrack *tmp = factory->NewWaveTrack( ((WaveTrack*)t)->GetSampleFormat(), ((WaveTrack*)t)->GetRate()); - tmp->InsertSilence(0.0, length-sel_len); - tmp->Flush(); - if ( !( ((WaveTrack *)t)->HandlePaste(t0+sel_len, tmp)) ) return false; + // if selection is smaller than the content to add then we + // need to add extra space in the group tracks. If the track + // is empty at this point insert whitespace; otherwise, + // silence + if (wt->IsEmpty(t0+sel_len, t0+sel_len)) + { + // Have to check if clips can move in this case + bool clipsCanMove = true; + gPrefs->Read(wxT("/GUI/EditClipCanMove"), &clipsCanMove); + if (clipsCanMove) + { + Track *tmp = NULL; + wt->Cut(t0 + sel_len, + wt->GetEndTime()+1.0/wt->GetRate(), &tmp, false); + wt->HandlePaste(t0 + length, tmp); + delete tmp; + } + } + else + { + TrackFactory *factory = p->GetTrackFactory(); + WaveTrack *tmp = factory->NewWaveTrack( wt->GetSampleFormat(), wt->GetRate()); + tmp->InsertSilence(0.0, length-sel_len); + tmp->Flush(); + wt->HandlePaste(t0+sel_len, tmp); + } } } } } else if (t->GetKind() == Track::Label) { LabelTrack *lt = (LabelTrack *)t; - if (relativeLabels && (sel_len != 0.0)) - lt->ScaleLabels(info->sel0, info->sel1, length/sel_len); - else { - if ((length - sel_len) > 0.0) - lt->ShiftLabelsOnInsert(length-sel_len, t0); - else if ((length - sel_len) < 0.0) - lt->ShiftLabelsOnClear(info->sel0+length, info->sel1); + if (!t->GetSelected()) + { + if (relativeLabels && (sel_len != 0.0)) + lt->ScaleLabels(info->sel0, info->sel1, length/sel_len); + else { + if ((length - sel_len) > 0.0) + lt->ShiftLabelsOnInsert(length-sel_len, t0); + else if ((length - sel_len) < 0.0) + lt->ShiftLabelsOnClear(info->sel0+length, info->sel1); + } } } } @@ -933,17 +991,21 @@ // the only behaviour which is different to what was done before, but it // shouldn't confuse users too much. // - // - If multiple clips should be pasted, these are always pasted as single - // clips, and the current clip is splitted, when necessary. This may seem - // strange at first, but it probably is better than trying to auto-merge - // anything. The user can still merge the clips by hand (which should be - // a simple command reachable by a hotkey or single mouse click). + // - If multiple clips should be pasted, or a single clip that does not fill + // the duration of the pasted track, these are always pasted as single + // clips, and the current clip is splitted, when necessary. This may seem + // strange at first, but it probably is better than trying to auto-merge + // anything. The user can still merge the clips by hand (which should be a + // simple command reachable by a hotkey or single mouse click). // if (other->GetNumClips() == 0) return false; //printf("paste: we have at least one clip\n"); + + bool singleClipMode = (other->GetNumClips() == 1 && + other->GetStartTime() == 0.0); double insertDuration = other->GetEndTime(); WaveClipList::compatibility_iterator it; @@ -952,7 +1014,7 @@ // Make room for the pasted data if (editClipCanMove) { - if (other->GetNumClips() > 1) { + if (!singleClipMode) { // We need to insert multiple clips, so split the current clip and // move everything to the right, then try to paste again if (!IsEmpty(t0, GetEndTime())) { @@ -974,7 +1036,7 @@ } } - if (other->GetNumClips() == 1) + if (singleClipMode) { // Single clip mode // printf("paste: checking for single clip mode!\n"); @@ -1054,11 +1116,15 @@ { WaveClip* clip = it->GetData(); - WaveClip* newClip = new WaveClip(*clip, mDirManager); - newClip->Resample(mRate); - newClip->Offset(t0); - newClip->MarkChanged(); - mClips.Append(newClip); + // AWD Oct. 2009: Don't actually paste in placeholder clips + if (!clip->GetIsPlaceholder()) + { + WaveClip* newClip = new WaveClip(*clip, mDirManager); + newClip->Resample(mRate); + newClip->Offset(t0); + newClip->MarkChanged(); + mClips.Append(newClip); + } } return true; } Index: Menus.cpp =================================================================== RCS file: /cvsroot/audacity/audacity-src/src/Menus.cpp,v retrieving revision 1.529 retrieving revision 1.530 diff -u -d -r1.529 -r1.530 --- Menus.cpp 18 Oct 2009 04:54:05 -0000 1.529 +++ Menus.cpp 18 Oct 2009 19:58:17 -0000 1.530 @@ -3299,6 +3299,10 @@ bool advanceClipboard = true; double srcLength = c->GetEndTime(); + // Keeps track of whether n would be the first WaveTrack in its group to + // receive data from the paste. + bool firstInGroup = true; + while (n && c) { if (n->GetSelected()) { advanceClipboard = true; @@ -3324,7 +3328,11 @@ if (!c){ c = tmpC; while (n && (c->GetKind() != n->GetKind()) ) + { n = iter.Next(); + if (n && n->GetKind() == Track::Label) + firstInGroup = true; + } if (!n) c = NULL; } @@ -3357,7 +3365,12 @@ ((WaveTrack *) c)->Lock(); if (c->GetKind() == Track::Wave && n && n->GetKind() == Track::Wave) - pastedSomething = ((WaveTrack*)n)->ClearAndPaste(t0, t1, (WaveTrack*)c); + { + // If not the first in group we set useHandlePaste to true + pastedSomething = ((WaveTrack*)n)->ClearAndPaste(t0, t1, + (WaveTrack*)c, true, true, NULL, false, !firstInGroup); + firstInGroup = !pastedSomething; + } else pastedSomething = n->Paste(t0, c); @@ -3372,12 +3385,23 @@ if (!((WaveTrack *) n)->IsEmpty(t0, t1)) { ((WaveTrack *) n)->Clear(t0, t1); } + + // firstInGroup should always be false here, unless pasting to + // the first channel failed + if (firstInGroup) + { + pastedSomething = ((WaveTrack *)n)->Paste(t0, c); + firstInGroup = !pastedSomething; + } + else + { + pastedSomething = ((WaveTrack *)n)->HandlePaste(t0, c); + } } else { - ((WaveTrack *) n)->Clear(t0, t1); + n->Clear(t0, t1); + n->Paste(t0, c); } - - n->Paste(t0, c); } if (msClipProject != this && c->GetKind() == Track::Wave) @@ -3390,6 +3414,8 @@ } n = iter.Next(); + if (n && n->GetKind() == Track::Label) + firstInGroup = true; } // This block handles the cases where our clipboard is smaller ------------------------------------------------------------------------------ Come build with us! The BlackBerry(R) Developer Conference in SF, CA is the only developer event you need to attend this year. Jumpstart your developing skills, take BlackBerry mobile applications to market and stay ahead of the curve. Join us from November 9 - 12, 2009. Register now! http://p.sf.net/sfu/devconference _______________________________________________ Audacity-cvs mailing list Audacity-cvs@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/audacity-cvs