wxString ControlToolBar::StateForStatusBar() { wxString state; auto pProject = GetActiveProject(); auto scrubState = pProject ? pProject->GetScrubber().GetUntranslatedStateString() : wxString(); if (!scrubState.IsEmpty()) state = wxGetTranslation(scrubState); else if (mPlay->IsDown()) state = wxGetTranslation(mStatePlay); else if (mRecord->IsDown()) state = wxGetTranslation(mStateRecord); else state = wxGetTranslation(mStateStop); if (mPause->IsDown()) { state.Append(wxT(" ")); state.Append(wxGetTranslation(mStatePause)); } state.Append(wxT(".")); return state; }
void ScrubbingOverlay::Draw (wxDC &dc, TrackPanelCellIterator, TrackPanelCellIterator) { mLastScrubRect = mNextScrubRect; mLastScrubSpeedText = mNextScrubSpeedText; Scrubber &scrubber = GetScrubber(); if (!scrubber.ShouldDrawScrubSpeed()) return; static const wxFont labelFont(24, wxSWISS, wxNORMAL, wxNORMAL); dc.SetFont(labelFont); // These two colors were previously saturated red and green. However // we have a rule to try to only use red for reserved purposes of // (a) Recording // (b) Error alerts // So they were changed to 'orange' and 'lime'. static const wxColour clrNoScroll(215, 162, 0), clrScroll(0, 204, 153); #ifdef EXPERIMENTAL_SCRUBBING_SMOOTH_SCROLL if (scrubber.IsScrollScrubbing()) dc.SetTextForeground(clrScroll); else #endif dc.SetTextForeground(clrNoScroll); dc.DrawText(mLastScrubSpeedText, mLastScrubRect.GetX(), mLastScrubRect.GetY()); }
std::pair<wxRect, bool> ScrubbingOverlay::DoGetRectangle(wxSize) { wxRect rect(mLastScrubRect); const bool outdated = (mLastScrubRect != mNextScrubRect) || (!mLastScrubRect.IsEmpty() && !GetScrubber().ShouldDrawScrubSpeed()) || (mLastScrubSpeedText != mNextScrubSpeedText); return std::make_pair( rect, outdated ); }
void ScrubbingToolBar::RegenerateTooltips() { #if wxUSE_TOOLTIPS std::vector<wxString> commands; auto fn = [&] (AButton &button, const wxString &label, const wxString &command) { commands.clear(); commands.push_back(label); commands.push_back(command); ToolBar::SetButtonToolTip(button, commands); }; auto project = GetActiveProject(); if (project) { auto &scrubber = project->GetScrubber(); const auto scrubButton = mButtons[STBScrubID]; const auto seekButton = mButtons[STBSeekID]; wxString label; label = ( scrubber.Scrubs() /* i18n-hint: These commands assist the user in finding a sound by ear. ... "Scrubbing" is variable-speed playback, ... "Seeking" is normal speed playback but with skips */ ? _("Stop Scrubbing") : _("Start Scrubbing") ); fn(*scrubButton, label, wxT("Scrub")); label = ( scrubber.Seeks() /* i18n-hint: These commands assist the user in finding a sound by ear. ... "Scrubbing" is variable-speed playback, ... "Seeking" is normal speed playback but with skips */ ? _("Stop Seeking") : _("Start Seeking") ); fn(*seekButton, label, wxT("Seek")); label = ( project->GetRulerPanel()->ShowingScrubBar() ? _("Hide Scrub Bar") : _("Show Scrub Bar") ); fn(*mButtons[STBBarID], label, wxT("ToggleScrubBar")); } #endif }
void ControlToolBar::EnableDisableButtons() { AudacityProject *p = GetActiveProject(); bool tracks = false; bool playing = mPlay->IsDown(); bool recording = mRecord->IsDown(); bool notBusy = !gAudioIO->IsBusy(); // Only interested in audio type tracks if (p) { TrackListIterator iter( p->GetTracks() ); for (Track *t = iter.First(); t; t = iter.Next()) { if (t->GetKind() == Track::Wave #if defined(USE_MIDI) || t->GetKind() == Track::Note #endif ) { tracks = true; break; } } } if (p) { TranscriptionToolBar *const playAtSpeedTB = p->GetTranscriptionToolBar(); if (playAtSpeedTB) playAtSpeedTB->SetEnabled(CanStopAudioStream() && tracks && !recording); } mPlay->SetEnabled(CanStopAudioStream() && tracks && !recording); mRecord->SetEnabled(CanStopAudioStream() && notBusy && !playing); mStop->SetEnabled(CanStopAudioStream() && (playing || recording)); mRewind->SetEnabled(!playing && !recording); mFF->SetEnabled(tracks && !playing && !recording); auto pProject = GetActiveProject(); mPause->SetEnabled(CanStopAudioStream() && !(pProject && pProject->GetScrubber().HasStartedScrubbing())); }
void ScrubbingOverlay::OnTimer(wxCommandEvent &event) { // Let other listeners get the notification event.Skip(); Scrubber &scrubber = GetScrubber(); if (!GetScrubber().IsScrubbing()) { mNextScrubRect = wxRect(); return; } // Call ContinueScrubbing() here in the timer handler // rather than in SelectionHandleDrag() // so that even without drag events, we can instruct the play head to // keep approaching the mouse cursor, when its maximum speed is limited. scrubber.ContinueScrubbing(); if (!scrubber.ShouldDrawScrubSpeed()) { mNextScrubRect = wxRect(); } else { TrackPanel *const trackPanel = mProject->GetTrackPanel(); int panelWidth, panelHeight; trackPanel->GetSize(&panelWidth, &panelHeight); // Where's the mouse? int xx, yy; ::wxGetMousePosition(&xx, &yy); trackPanel->ScreenToClient(&xx, &yy); const bool seeking = scrubber.PollIsSeeking(); // Find the text const double maxScrubSpeed = GetScrubber().GetMaxScrubSpeed(); const double speed = #ifdef EXPERIMENTAL_SCRUBBING_SMOOTH_SCROLL scrubber.IsScrollScrubbing() ? scrubber.FindScrubSpeed (seeking, mProject->GetViewInfo().PositionToTime(xx, trackPanel->GetLeftOffset())) : #endif maxScrubSpeed; const wxChar *format = #ifdef EXPERIMENTAL_SCRUBBING_SMOOTH_SCROLL scrubber.IsScrollScrubbing() ? seeking ? wxT("%+.2fX") : wxT("%+.2f") : #endif wxT("%.2f"); mNextScrubSpeedText = wxString::Format(format, speed); // Find the origin for drawing text wxCoord width, height; { wxClientDC dc(trackPanel); static const wxFont labelFont(24, wxSWISS, wxNORMAL, wxNORMAL); dc.SetFont(labelFont); dc.GetTextExtent(mNextScrubSpeedText, &width, &height); } xx = std::max(0, std::min(panelWidth - width, xx - width / 2)); // Put the text above the cursor, if it fits. enum { offset = 20 }; yy -= height + offset; if (yy < 0) yy += height + 2 * offset; yy = std::max(0, std::min(panelHeight - height, yy)); mNextScrubRect = wxRect(xx, yy, width, height); } }