Audacity  3.0.3
Lyrics.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 
3  Audacity: A Digital Audio Editor
4 
5  Lyrics.cpp
6 
7  Dominic Mazzoni
8  Vaughan Johnson
9 
10 **********************************************************************/
11 
12 #include "Lyrics.h"
13 
14 #include <math.h>
15 
16 #include <wx/dcclient.h>
17 #include <wx/defs.h>
18 #include <wx/dcmemory.h>
19 #include <wx/frame.h>
20 #include <wx/mimetype.h>
21 
22 #include "AudioIO.h"
23 #include "Project.h"
24 #include "ProjectWindowBase.h"
25 #include "LabelTrack.h"
27 #include "UndoManager.h"
28 #include "ViewInfo.h"
29 
30 
31 BEGIN_EVENT_TABLE(HighlightTextCtrl, wxTextCtrl)
32  EVT_MOUSE_EVENTS(HighlightTextCtrl::OnMouseEvent)
34 
36  wxWindowID id,
37  const wxString& value /* = {} */,
38  const wxPoint& pos /*= wxDefaultPosition*/,
39  const wxSize& size /*= wxDefaultSize*/)
40 : wxTextCtrl(parent, id, // wxWindow* parent, wxWindowID id,
41  value, // const wxString& value = {},
42  pos, // const wxPoint& pos = wxDefaultPosition,
43  size, // const wxSize& size = wxDefaultSize,
44  wxTE_MULTILINE | wxTE_READONLY | wxTE_RICH | wxTE_RICH2 | wxTE_AUTO_URL | wxTE_NOHIDESEL), //v | wxHSCROLL)
45  mLyricsPanel(parent)
46 {
47 }
48 
49 void HighlightTextCtrl::OnMouseEvent(wxMouseEvent& event)
50 {
51  if (event.ButtonUp())
52  {
53  long from, to;
54  this->GetSelection(&from, &to);
55 
56  int nCurSyl = mLyricsPanel->GetCurrentSyllableIndex();
57  int nNewSyl = mLyricsPanel->FindSyllable(from);
58  if (nNewSyl != nCurSyl)
59  {
60  Syllable* pCurSyl = mLyricsPanel->GetSyllable(nNewSyl);
61  auto pProj = FindProjectFromWindow( this );
62  auto &selectedRegion = ViewInfo::Get( *pProj ).selectedRegion;
63  selectedRegion.setT0( pCurSyl->t );
64 
65  //v Should probably select to end as in
66  // SelectUtilities::Handler::OnSelectCursorEnd,
67  // but better to generalize that in AudacityProject methods.
68  selectedRegion.setT1( pCurSyl->t );
69  }
70  }
71 
72  event.Skip();
73 }
74 
75 
76 //v static const kHighlightTextCtrlID = 7654;
77 
78 BEGIN_EVENT_TABLE(LyricsPanel, wxPanelWrapper)
79  EVT_KEY_DOWN(LyricsPanel::OnKeyEvent)
80  EVT_PAINT(LyricsPanel::OnPaint)
81  EVT_SIZE(LyricsPanel::OnSize)
82 
83  //v Doesn't seem to be a way to capture a selection event in a read-only wxTextCtrl.
84  // EVT_COMMAND_LEFT_CLICK(kHighlightTextCtrlID, LyricsPanel::OnHighlightTextCtrl)
86 
88 
89 LyricsPanel::LyricsPanel(wxWindow* parent, wxWindowID id,
90  AudacityProject *project,
91  const wxPoint& pos /*= wxDefaultPosition*/,
92  const wxSize& size /*= wxDefaultSize*/) :
93  wxPanelWrapper(parent, id, pos, size, wxWANTS_CHARS),
94  mWidth(size.x), mHeight(size.y)
95  , mProject(project)
96 {
97  mKaraokeHeight = mHeight;
98  mLyricsStyle = kBouncingBallLyrics; // default
99  mKaraokeFontSize = this->GetDefaultFontSize(); // Call only after mLyricsPanelStyle is set.
100 
101  this->SetBackgroundColour(*wxWHITE);
102 
103  mHighlightTextCtrl =
104  safenew HighlightTextCtrl(this, -1, // wxWindow* parent, wxWindowID id,
105  wxT(""), // const wxString& value = {},
106  wxPoint(0, 0), // const wxPoint& pos = wxDefaultPosition,
107  size); // const wxSize& size = wxDefaultSize
108  this->SetHighlightFont();
109  mHighlightTextCtrl->Show(mLyricsStyle == kHighlightLyrics); // test, in case we conditionalize the default, above
110 
111 
112  mT = 0.0;
113 
114  Clear();
115  Finish(0.0);
116 
117  #ifdef __WXMAC__
118  wxSizeEvent dummyEvent;
119  OnSize(dummyEvent);
120  #endif
121 
122  parent->Bind(wxEVT_SHOW, &LyricsPanel::OnShow, this);
123 
124  project->Bind(EVT_UNDO_PUSHED, &LyricsPanel::UpdateLyrics, this);
125  project->Bind(EVT_UNDO_MODIFIED, &LyricsPanel::UpdateLyrics, this);
126  project->Bind(EVT_UNDO_OR_REDO, &LyricsPanel::UpdateLyrics, this);
127  project->Bind(EVT_UNDO_RESET, &LyricsPanel::UpdateLyrics, this);
128 
129  wxTheApp->Bind(EVT_AUDIOIO_PLAYBACK, &LyricsPanel::OnStartStop, this);
130  wxTheApp->Bind(EVT_AUDIOIO_CAPTURE, &LyricsPanel::OnStartStop, this);
131 }
132 
134 {
135 }
136 
137 #define I_FIRST_REAL_SYLLABLE 2
138 
140 {
141  mSyllables.clear();
142  mText = wxT("");
143 
144  // Add two dummy syllables at the beginning
145  mSyllables.push_back(Syllable());
146  mSyllables[0].t = -2.0;
147  mSyllables.push_back(Syllable());
148  mSyllables[1].t = -1.0;
149 
150  mHighlightTextCtrl->Clear();
151 }
152 
154 {
155  const size_t numLabels = pLT->GetNumLabels();
156  wxString highlightText;
157  for (size_t ii = 0; ii < numLabels; ++ii) {
158  const LabelStruct *const pLabel = pLT->GetLabel(ii);
159  Add(pLabel->getT0(), pLabel->title, highlightText);
160  }
161  mHighlightTextCtrl->AppendText(highlightText);
162 }
163 
164 void LyricsPanel::Add(double t, const wxString &syllable, wxString &highlightText)
165 {
166  int i = mSyllables.size();
167 
168  {
169  Syllable &prevSyllable = mSyllables[i - 1];
170 
171  if (prevSyllable.t == t) {
172  // We can't have two syllables with the same time, so append
173  // this to the end of the previous one if they're at the
174  // same time.
175  prevSyllable.text += syllable;
176  prevSyllable.textWithSpace += syllable;
177  prevSyllable.char1 += syllable.length();
178  return;
179  }
180  }
181 
182  mSyllables.push_back(Syllable());
183  Syllable &thisSyllable = mSyllables[i];
184  thisSyllable.t = t;
185  thisSyllable.text = syllable;
186 
187  thisSyllable.char0 = mText.length();
188 
189  // Put a space between syllables unless the previous one
190  // ended in a hyphen
191  if (i > 0 &&
192  // mSyllables[i-1].text.length() > 0 &&
193  mSyllables[i - 1].text.Right(1) != wxT("-"))
194  thisSyllable.textWithSpace = wxT(" ") + syllable;
195  else
196  thisSyllable.textWithSpace = syllable;
197 
198  mText += thisSyllable.textWithSpace;
199  thisSyllable.char1 = mText.length();
200 
201  int nTextLen = thisSyllable.textWithSpace.length();
202  if ((nTextLen > 0) && (thisSyllable.textWithSpace.Right(1) == wxT("_")))
203  highlightText += (thisSyllable.textWithSpace.Left(nTextLen - 1) + wxT("\n"));
204  else
205  highlightText += thisSyllable.textWithSpace;
206 }
207 
208 void LyricsPanel::Finish(double finalT)
209 {
210  // Add 3 dummy syllables at the end
211  int i = mSyllables.size();
212  mSyllables.push_back(Syllable());
213  mSyllables[i].t = finalT + 1.0;
214  mSyllables.push_back(Syllable());
215  mSyllables[i+1].t = finalT + 2.0;
216  mSyllables.push_back(Syllable());
217  mSyllables[i+2].t = finalT + 3.0;
218 
219  // Mark measurements as invalid
220  mMeasurementsDone = false; // only for drawn text
221  mCurrentSyllable = 0;
222  mHighlightTextCtrl->ShowPosition(0);
223 }
224 
225 // Binary-search for the syllable whose char0 <= startChar <= char1.
226 int LyricsPanel::FindSyllable(long startChar)
227 {
228  int i1, i2;
229 
230  i1 = 0;
231  i2 = mSyllables.size();
232  while (i2 > i1+1) {
233  int pmid = (i1+i2)/2;
234  if (mSyllables[pmid].char0 > startChar)
235  i2 = pmid;
236  else
237  i1 = pmid;
238  }
239 
240  if (i1 < 2)
241  i1 = 2;
242  if (i1 > (int)(mSyllables.size()) - 3)
243  i1 = mSyllables.size() - 3;
244 
245  return i1;
246 }
247 
248 void LyricsPanel::SetLyricsStyle(const LyricsStyle newLyricsStyle)
249 {
250  if (mLyricsStyle == newLyricsStyle)
251  return;
252 
253  mLyricsStyle = newLyricsStyle;
255 
256  wxSizeEvent ignore;
257  this->OnSize(ignore);
258 }
259 
260 
262 {
263  return (mLyricsStyle == kBouncingBallLyrics) ? 48 : 10;
264 }
265 
267 {
268  dc->SetFont(wxFont(mKaraokeFontSize, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL));
269 }
270 
271 void LyricsPanel::SetHighlightFont() // for kHighlightLyrics
272 {
273  wxFont newFont(mKaraokeFontSize, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
274  mHighlightTextCtrl->SetDefaultStyle(wxTextAttr(wxNullColour, wxNullColour, newFont));
275  mHighlightTextCtrl->SetStyle(0, mHighlightTextCtrl->GetLastPosition(),
276  wxTextAttr(wxNullColour, wxNullColour, newFont));
277 }
278 
279 void LyricsPanel::Measure(wxDC *dc) // only for drawn text
280 {
281  this->SetDrawnFont(dc);
282  int width = 0, height = 0;
283 
284  const int kIndent = 4;
285  int x = 2*kIndent;
286 
287  unsigned int i;
288  for(i = 0; i < mSyllables.size(); i++) {
289  if ((i < I_FIRST_REAL_SYLLABLE) || // Clear() starts the list with I_FIRST_REAL_SYLLABLE dummies.
290  (i >= mSyllables.size() - 3)) // Finish() ends with 3 dummies.
291  {
292  dc->GetTextExtent(wxT("DUMMY"), &width, &height); // Get the correct height even if we're at i=0.
293  width = 0;
294  }
295  else {
296  dc->GetTextExtent(mSyllables[i].textWithSpace, &width, &height);
297  }
298 
299  // Add some space between words; the space is normally small but
300  // when there's a long pause relative to the previous word, insert
301  // extra space.
302  int extraWidth;
303  if (i >= I_FIRST_REAL_SYLLABLE && i < mSyllables.size() - 2)
304  {
305  double deltaThis = mSyllables[i+1].t - mSyllables[i].t;
306  double deltaPrev = mSyllables[i].t - mSyllables[i-1].t;
307 
308  double ratio;
309  if (deltaPrev > 0.0)
310  ratio = deltaThis / deltaPrev;
311  else
312  ratio = deltaThis;
313 
314  if (ratio > 2.0)
315  extraWidth = 15 + (int)(15.0 * ratio);
316  else
317  extraWidth = 15;
318  }
319  else
320  extraWidth = 20;
321 
322  mSyllables[i].width = width + extraWidth;
323  mSyllables[i].leftX = x;
324  mSyllables[i].x = x + width/2;
325  x += mSyllables[i].width;
326  }
327 
328  mTextHeight = height;
329 
330  mMeasurementsDone = true;
331 }
332 
333 // Binary-search for the syllable with the largest time not greater than t
335 {
336  int i1, i2;
337 
338  i1 = 0;
339  i2 = mSyllables.size();
340  while (i2 > i1+1) {
341  int pmid = (i1+i2)/2;
342  if (mSyllables[pmid].t > t)
343  i2 = pmid;
344  else
345  i1 = pmid;
346  }
347 
348  if (i1 < 2)
349  i1 = 2;
350  if (i1 > (int)(mSyllables.size()) - 3)
351  i1 = mSyllables.size() - 3;
352 
353  return i1;
354 }
355 
356 // Bouncing Ball:
357 // Given the current time t, returns the x/y position of the scrolling
358 // karaoke display. For some syllable i, when t==mSyllables[i].t,
359 // it will return mSyllables[i].x for outX and 0 for outY.
360 // In-between words, outX is interpolated using smooth acceleration
361 // between the two neighboring words, and y is a positive number indicating
362 // the bouncing ball height
364  int *outX, double *outY)
365 {
366  *outX = 0;
367  *outY = 0;
368 
369  if (t < mSyllables[I_FIRST_REAL_SYLLABLE].t || t > mSyllables[mSyllables.size() - 3].t)
370  return;
371 
372  int i0, i1, i2, i3;
373  int x0, x1, x2, x3;
374  double t0, t1, t2, t3;
375  i1 = FindSyllable(t);
376  i2 = i1 + 1;
377 
378  // Because we've padded the syllables with two dummies at the beginning
379  // and end, we know that i0...i3 will always exist. Also, we've made
380  // sure that we don't ever have two of the same time, so t2>t1 strictly.
381  //
382  // t
383  // \/
384  // time: t0 t1 t2 t3
385  // pos: x0 x1 x2 x3
386  // index: i0 i1 i2 i3
387  // vel: vel1 vel2
388 
389  i0 = i1 - 1;
390  i3 = i2 + 1;
391 
392  x0 = mSyllables[i0].x;
393  x1 = mSyllables[i1].x;
394  x2 = mSyllables[i2].x;
395  x3 = mSyllables[i3].x;
396 
397  t0 = mSyllables[i0].t;
398  t1 = mSyllables[i1].t;
399  t2 = mSyllables[i2].t;
400  t3 = mSyllables[i3].t;
401 
402  double linear_vel0 = (x1 - x0) / (t1 - t0);
403  double linear_vel1 = (x2 - x1) / (t2 - t1);
404  double linear_vel2 = (x3 - x2) / (t3 - t2);
405 
406  // average velocities
407  double v1 = (linear_vel0 + linear_vel1) / 2;
408  double v2 = (linear_vel1 + linear_vel2) / 2;
409 
410  // Solve a cubic equation f(t) = at^3 + bt^2 + ct + d
411  // which gives the position x as a function of
412  // (t - t1), by constraining f(0), f'(0), f(t2-t1), f'(t2-t1)
413  double delta_t = t2 - t1;
414  double delta_x = x2 - x1;
415  v1 *= delta_t;
416  v2 *= delta_t;
417  double a = v1 + v2 - 2*delta_x;
418  double b = 3*delta_x - 2*v1 - v2;
419  double c = v1;
420  double d = x1;
421 
422  t = (t - t1) / (t2 - t1);
423  double xx = a*t*t*t + b*t*t + c*t + d;
424 
425  // Unfortunately sometimes our cubic goes backwards. This is a quick
426  // hack to stop that from happening.
427  if (xx < x1)
428  xx = x1;
429 
430  *outX = (int)xx;
431 
432  // The y position is a simple cosine curve; the max height is a
433  // function of the time.
434  double height = t2 - t1 > 4.0? 1.0: sqrt((t2-t1)/4.0);
435  *outY = height * sin(M_PI * t);
436 }
437 
438 void LyricsPanel::Update(double t)
439 {
440  if (t < 0.0)
441  {
442  // TrackPanel::OnTimer passes gAudioIO->GetStreamTime(), which is -DBL_MAX if !IsStreamActive().
443  // In that case, use the selection start time.
444  auto pProj = FindProjectFromWindow( this );
445  const auto &selectedRegion = ViewInfo::Get( *pProj ).selectedRegion;
446  mT = selectedRegion.t0();
447  }
448  else
449  mT = t;
450 
452  {
453  wxRect karaokeRect(0, 0, mWidth, mKaraokeHeight);
454  this->Refresh(false, &karaokeRect);
455  }
456 
457  int i = FindSyllable(mT);
458  if (i == mCurrentSyllable)
459  return;
460 
461  mCurrentSyllable = i;
462 
464  {
465  mHighlightTextCtrl->SetSelection(mSyllables[i].char0, mSyllables[i].char1);
466 
467  //v No trail for now.
469  //if (i == I_FIRST_REAL_SYLLABLE)
470  // // Reset the trail to zero.
471  // mHighlightTextCtrl->SetStyle(0, mHighlightTextCtrl->GetLastPosition(), wxTextAttr(wxNullColour, *wxWHITE));
473  //mHighlightTextCtrl->SetStyle(mSyllables[i].char0, mSyllables[i].char1, wxTextAttr(wxNullColour, *wxLIGHT_GREY));
474 
475  //v Too much flicker: mHighlightTextCtrl->ShowPosition(mSyllables[i].char0);
476  }
477 }
478 
480 {
481  e.Skip();
482 
483  // It's crucial to not do that repopulating during playback.
484  auto gAudioIO = AudioIOBase::Get();
485  if (gAudioIO->IsStreamActive()) {
486  mDelayedUpdate = true;
487  return;
488  }
489 
490  Clear();
491 
492  if (!mProject)
493  return;
494 
495  // Lyrics come from only the first label track.
496  auto pLabelTrack =
497  *TrackList::Get( *mProject ).Any< const LabelTrack >().begin();
498  if (!pLabelTrack)
499  return;
500 
501  // The code that updates the lyrics is rather expensive when there
502  // are a lot of labels.
503  // So - bail out early if the lyrics window is not visible.
504  // We will later force an update when the lyrics window is made visible.
505  auto parent = dynamic_cast<wxFrame*>(GetParent());
506  if( !(parent && parent->IsVisible()) )
507  return;
508 
509  AddLabels(pLabelTrack);
510  Finish(pLabelTrack->GetEndTime());
511  const auto &selectedRegion = ViewInfo::Get( *mProject ).selectedRegion;
512  Update(selectedRegion.t0());
513 }
514 
515 void LyricsPanel::OnStartStop(wxCommandEvent &e)
516 {
517  e.Skip();
518  if ( !e.GetInt() && mDelayedUpdate ) {
519  mDelayedUpdate = false;
520  UpdateLyrics( e );
521  }
522 }
523 
524 void LyricsPanel::OnShow(wxShowEvent &e)
525 {
526  e.Skip();
527  if (e.IsShown())
528  UpdateLyrics(e);
529 }
530 
531 void LyricsPanel::OnKeyEvent(wxKeyEvent & event)
532 {
533  auto project = FindProjectFromWindow( this );
534  auto &commandManager = CommandManager::Get( *project );
535  commandManager.FilterKeyEvent(project, event, true);
536  event.Skip();
537 }
538 
539 void LyricsPanel::OnPaint(wxPaintEvent & WXUNUSED(event))
540 {
541  wxPaintDC dc(this);
542  DoPaint(dc);
543 }
544 
545 void LyricsPanel::DoPaint(wxDC &dc)
546 {
547  if (!this->GetParent()->IsShown())
548  return;
549 
551  {
552  if (!mMeasurementsDone)
553  Measure(&dc);
554 
555  #ifdef __WXMAC__
556  // Mac OS X automatically double-buffers the screen for you,
557  // so our bitmap is unnecessary
558  HandlePaint(dc);
559  #else
560  wxBitmap bitmap(mWidth, mKaraokeHeight);
561  wxMemoryDC memDC;
562  memDC.SelectObject(bitmap);
563  HandlePaint(memDC);
564  dc.Blit(0, 0, mWidth, mKaraokeHeight, &memDC, 0, 0, wxCOPY, FALSE);
565  #endif
566  }
567  else // (mLyricsStyle == kHighlightLyrics)
568  {
569  //v causes flicker in ported version
570  // this->SetHighlightFont();
571  }
572 }
573 
574 void LyricsPanel::OnSize(wxSizeEvent & WXUNUSED(event))
575 {
576  GetClientSize(&mWidth, &mHeight);
577 
579 
581  (int)((float)(this->GetDefaultFontSize() * mHeight) / (float)LYRICS_DEFAULT_HEIGHT);
582  // Usually don't get the size window we want, usually less than
583  // LYRICS_DEFAULT_HEIGHT, so bump it a little.
584  mKaraokeFontSize += 2;
585 
587  {
588  mMeasurementsDone = false;
589  wxClientDC dc(this);
590  this->DoPaint(dc);
591  }
592  else // (mLyricsStyle == kHighlightLyrics)
593  {
595  this->SetHighlightFont();
596  }
597 
598  this->Refresh(false);
599 }
600 
601 //v Doesn't seem to be a way to capture a selection event in a read-only wxTextCtrl.
602 //void LyricsPanel::OnHighlightTextCtrl(wxCommandEvent & event)
603 //{
604 // long from, to;
605 //
606 // mHighlightTextCtrl->GetSelection(&from, &to);
607 // // TODO: Find the start time of the corresponding syllable and set playback to start there.
608 //}
609 
611 {
612  wxASSERT(mLyricsStyle == kBouncingBallLyrics);
613  dc.SetBrush(*wxWHITE_BRUSH);
614  dc.DrawRectangle(0, 0, mWidth, mKaraokeHeight);
615 
616  this->HandlePaint_BouncingBall(dc);
617 }
618 
620 {
621  int ctr = mWidth / 2;
622  int x;
623  double y;
624  GetKaraokePosition(mT, &x, &y);
625 
626  dc.SetTextForeground(wxColour(238, 0, 102));
627  bool changedColor = false;
628 
629  SetDrawnFont(&dc);
630  unsigned int i;
631  wxCoord yTextTop = mKaraokeHeight - mTextHeight - 4;
632  for(i = 0; i < mSyllables.size(); i++) {
633  if (mSyllables[i].x + mSyllables[i].width < (x - ctr))
634  continue;
635  if (mSyllables[i].x > x + ctr)
636  continue;
637 
638  if (!changedColor && mSyllables[i].x >= x) {
639  dc.SetTextForeground(*wxBLACK);
640  changedColor = true;
641  }
642 
643  wxString text = mSyllables[i].text;
644  if (text.length() > 0 && text.Right(1) == wxT("_")) {
645  text = text.Left(text.length() - 1);
646  }
647 
648  dc.DrawText(text,
649  mSyllables[i].leftX + ctr - x,
650  yTextTop);
651  }
652 
653  int ballRadius = (int)(mTextHeight / 8.0);
654  int bounceTop = ballRadius * 2;
655  int bounceHeight = yTextTop - bounceTop;
656  int yi = (int)(yTextTop - 4 - (y * bounceHeight));
657 
658  if (mT >= 0.0) {
659  wxRect ball(ctr - ballRadius, yi - ballRadius, 2 * ballRadius, 2 * ballRadius);
660  dc.SetBrush(wxBrush(wxColour(238, 0, 102), wxBRUSHSTYLE_SOLID));
661  dc.DrawEllipse(ball);
662  }
663 }
664 
ViewInfo::Get
static ViewInfo & Get(AudacityProject &project)
Definition: ViewInfo.cpp:156
LyricsPanel::Measure
void Measure(wxDC *dc)
Definition: Lyrics.cpp:279
LyricsPanel::~LyricsPanel
virtual ~LyricsPanel()
Definition: Lyrics.cpp:133
LyricsPanel::GetDefaultFontSize
unsigned int GetDefaultFontSize() const
Definition: Lyrics.cpp:261
LyricsPanel::UpdateLyrics
void UpdateLyrics(wxEvent &e)
Definition: Lyrics.cpp:479
LyricsPanel::mDelayedUpdate
bool mDelayedUpdate
Definition: Lyrics.h:160
LyricsPanel::mMeasurementsDone
bool mMeasurementsDone
Definition: Lyrics.h:157
ProjectWindowBase.h
LabelStruct::title
wxString title
Definition: LabelTrack.h:71
LyricsPanel::mKaraokeHeight
int mKaraokeHeight
Definition: Lyrics.h:144
LyricsPanel::HandlePaint_BouncingBall
void HandlePaint_BouncingBall(wxDC &dc)
Definition: Lyrics.cpp:619
Project.h
wxPanelWrapper
Definition: wxPanelWrapper.h:41
LyricsPanel::OnKeyEvent
void OnKeyEvent(wxKeyEvent &event)
Definition: Lyrics.cpp:531
LyricsPanel::GetCurrentSyllableIndex
int GetCurrentSyllableIndex()
Definition: Lyrics.h:95
LyricsPanel::SetDrawnFont
void SetDrawnFont(wxDC *dc)
Definition: Lyrics.cpp:266
CommandManager.h
LyricsPanel::OnShow
void OnShow(wxShowEvent &e)
Definition: Lyrics.cpp:524
Syllable::text
wxString text
Definition: Lyrics.h:39
LabelTrack
A LabelTrack is a Track that holds labels (LabelStruct).
Definition: LabelTrack.h:88
LyricsPanel::Clear
void Clear()
Definition: Lyrics.cpp:139
FindProjectFromWindow
AudacityProject * FindProjectFromWindow(wxWindow *pWindow)
Definition: ProjectWindowBase.cpp:39
HighlightTextCtrl::mLyricsPanel
LyricsPanel * mLyricsPanel
Definition: Lyrics.h:64
LabelStruct
A LabelStruct holds information for ONE label in a LabelTrack.
Definition: LabelTrack.h:30
OnSize
static void OnSize(wxSizeEvent &evt)
Definition: VSTEffect.cpp:2789
I_FIRST_REAL_SYLLABLE
#define I_FIRST_REAL_SYLLABLE
Definition: Lyrics.cpp:137
LyricsPanel::mSyllables
std::vector< Syllable > mSyllables
Definition: Lyrics.h:153
LyricsPanel::mKaraokeFontSize
unsigned int mKaraokeFontSize
Definition: Lyrics.h:145
LyricsPanel::mWidth
int mWidth
Definition: Lyrics.h:141
LyricsPanel::SetLyricsStyle
void SetLyricsStyle(const LyricsStyle newLyricsStyle)
Definition: Lyrics.cpp:248
Syllable::char0
int char0
Definition: Lyrics.h:41
Syllable::textWithSpace
wxString textWithSpace
Definition: Lyrics.h:40
ViewInfo::selectedRegion
NotifyingSelectedRegion selectedRegion
Definition: ViewInfo.h:199
LyricsPanel::mLyricsStyle
LyricsStyle mLyricsStyle
Definition: Lyrics.h:147
LyricsPanel::kHighlightLyrics
@ kHighlightLyrics
Definition: Lyrics.h:84
LyricsPanel::mTextHeight
int mTextHeight
Definition: Lyrics.h:156
LyricsPanel::kBouncingBallLyrics
@ kBouncingBallLyrics
Definition: Lyrics.h:82
LabelStruct::getT0
double getT0() const
Definition: LabelTrack.h:40
LyricsPanel::OnPaint
void OnPaint(wxPaintEvent &evt)
Definition: Lyrics.cpp:539
LyricsPanel::HandlePaint
void HandlePaint(wxDC &dc)
Definition: Lyrics.cpp:610
LyricsPanel::mCurrentSyllable
int mCurrentSyllable
Definition: Lyrics.h:152
LyricsPanel::OnStartStop
void OnStartStop(wxCommandEvent &e)
Definition: Lyrics.cpp:515
LYRICS_DEFAULT_HEIGHT
#define LYRICS_DEFAULT_HEIGHT
Definition: Lyrics.h:27
AudioIOBase::Get
static AudioIOBase * Get()
Definition: AudioIOBase.cpp:94
UndoManager.h
LyricsPanel::SetHighlightFont
void SetHighlightFont()
Definition: Lyrics.cpp:271
LyricsPanel::mProject
wxWeakRef< AudacityProject > mProject
Definition: Lyrics.h:159
LyricsPanel::Add
void Add(double t, const wxString &syllable, wxString &highlightText)
Definition: Lyrics.cpp:164
ViewInfo.h
LabelTrack.h
Syllable::char1
int char1
Definition: Lyrics.h:42
LyricsPanel::GetKaraokePosition
void GetKaraokePosition(double t, int *outX, double *outY)
Definition: Lyrics.cpp:363
LyricsPanel::mHighlightTextCtrl
HighlightTextCtrl * mHighlightTextCtrl
Definition: Lyrics.h:148
Syllable::t
double t
Definition: Lyrics.h:38
LyricsPanel::FindSyllable
int FindSyllable(long startChar)
Definition: Lyrics.cpp:226
LabelTrack::GetNumLabels
int GetNumLabels() const
Definition: LabelTrack.cpp:920
HighlightTextCtrl
Definition: Lyrics.h:52
Syllable
used in LyricsPanel, a Syllable gives positional information to be used with the bouncing ball effect...
Definition: Lyrics.h:31
TrackList::Get
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:495
LyricsPanel::LyricsStyle
LyricsStyle
Definition: Lyrics.h:81
LyricsPanel
LyricsPanel is a panel that paints the bouncing ball and the lyrics text.
Definition: Lyrics.h:78
AudioIO.h
AudacityProject
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:112
LyricsPanel::mText
wxString mText
Definition: Lyrics.h:154
IMPLEMENT_CLASS
IMPLEMENT_CLASS(ControlToolBar, ToolBar)
LyricsPanel::Finish
void Finish(double finalT)
Definition: Lyrics.cpp:208
M_PI
#define M_PI
Definition: Distortion.cpp:29
LabelTrack::GetLabel
const LabelStruct * GetLabel(int index) const
Definition: LabelTrack.cpp:925
NotifyingSelectedRegion::setT0
bool setT0(double t, bool maySwap=true)
Definition: ViewInfo.cpp:67
LyricsPanel::AddLabels
void AddLabels(const LabelTrack *pLT)
Definition: Lyrics.cpp:153
LyricsPanel::Update
void Update(double t)
Definition: Lyrics.cpp:438
TrackList::Any
auto Any() -> TrackIterRange< TrackType >
Definition: Track.h:1354
CommandManager::Get
static CommandManager & Get(AudacityProject &project)
Definition: CommandManager.cpp:202
safenew
#define safenew
Definition: MemoryX.h:10
LyricsPanel::mHeight
int mHeight
Definition: Lyrics.h:142
LyricsPanel::GetSyllable
Syllable * GetSyllable(int nSyl)
Definition: Lyrics.h:96
END_EVENT_TABLE
END_EVENT_TABLE()
Lyrics.h
LyricsPanel::DoPaint
void DoPaint(wxDC &dc)
Definition: Lyrics.cpp:545
HighlightTextCtrl::OnMouseEvent
void OnMouseEvent(wxMouseEvent &evt)
Definition: Lyrics.cpp:49
LyricsPanel::mT
double mT
Definition: Lyrics.h:150
LyricsPanel::OnSize
void OnSize(wxSizeEvent &evt)
Definition: Lyrics.cpp:574