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