1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-12-04 15:50:10 +01:00

Fix for http://bugzilla.audacityteam.org/show_bug.cgi?id=643 "Residual consistency issues with SHIFT showing Loop Play button icon" by Paul Licameli.

* Loop play-at-speed and cut preview play-at-speed implemented.
* Shift or ctrl down now affect all relevant buttons, loop or cut preview, normal or at speed, and append-record.
This commit is contained in:
james.k.crook@gmail.com
2014-11-29 17:22:05 +00:00
parent 30500b2e85
commit 7324997db6
14 changed files with 4503 additions and 4231 deletions

View File

@@ -49,6 +49,7 @@
#include <wx/tooltip.h>
#include "ControlToolBar.h"
#include "TranscriptionToolBar.h"
#include "MeterToolBar.h"
#include "../AColor.h"
@@ -72,7 +73,6 @@ AudacityProject *ControlToolBar::mBusyProject = NULL;
BEGIN_EVENT_TABLE(ControlToolBar, ToolBar)
EVT_CHAR(ControlToolBar::OnKeyEvent)
EVT_TIMER(wxID_ANY, ControlToolBar::OnTimer)
EVT_BUTTON(ID_PLAY_BUTTON, ControlToolBar::OnPlay)
EVT_BUTTON(ID_STOP_BUTTON, ControlToolBar::OnStop)
EVT_BUTTON(ID_RECORD_BUTTON, ControlToolBar::OnRecord)
@@ -89,8 +89,6 @@ END_EVENT_TABLE()
ControlToolBar::ControlToolBar()
: ToolBar(TransportBarID, _("Transport"), wxT("Control"))
{
mShiftKeyTimer.SetOwner(this);
mPaused = false;
gPrefs->Read(wxT("/GUI/ErgonomicTransportButtons"), &mErgonomicTransportButtons, true);
@@ -102,31 +100,12 @@ ControlToolBar::ControlToolBar()
ControlToolBar::~ControlToolBar()
{
wxTheApp->Disconnect( wxEVT_KEY_DOWN,
wxKeyEventHandler( ControlToolBar::OnKeyDown ),
NULL,
this );
wxTheApp->Disconnect( wxEVT_KEY_UP,
wxKeyEventHandler( ControlToolBar::OnKeyUp ),
NULL,
this );
}
void ControlToolBar::Create(wxWindow * parent)
{
ToolBar::Create(parent);
wxTheApp->Connect( wxEVT_KEY_DOWN,
wxKeyEventHandler( ControlToolBar::OnKeyDown ),
NULL,
this );
wxTheApp->Connect( wxEVT_KEY_UP,
wxKeyEventHandler( ControlToolBar::OnKeyUp ),
NULL,
this );
}
// This is a convenience function that allows for button creation in
@@ -148,27 +127,16 @@ AButton *ControlToolBar::MakeButton(teBmps eEnabledUp, teBmps eEnabledDown, teBm
return r;
}
void ControlToolBar::MakeLoopImage()
// static
void ControlToolBar::MakeAlternateImages(AButton &button, int idx,
teBmps eEnabledUp,
teBmps eEnabledDown,
teBmps eDisabled)
{
// JKC: See ToolBar::MakeButton() for almost identical code. Condense??
wxSize Size1( theTheme.ImageSize( bmpRecoloredUpLarge ));
wxSize Size2( theTheme.ImageSize( bmpLoop ));
int xoff = (Size1.GetWidth() - Size2.GetWidth())/2;
int yoff = (Size1.GetHeight() - Size2.GetHeight())/2;
wxImage * up2 = OverlayImage(bmpRecoloredUpLarge, bmpLoop, xoff, yoff);
wxImage * hilite2 = OverlayImage(bmpRecoloredHiliteLarge, bmpLoop, xoff, yoff);
wxImage * down2 = OverlayImage(bmpRecoloredDownLarge, bmpLoop, xoff + 1, yoff + 1);
wxImage * disable2 = OverlayImage(bmpRecoloredUpLarge, bmpLoopDisabled, xoff, yoff);
mPlay->SetAlternateImages(*up2, *hilite2, *down2, *disable2);
delete up2;
delete hilite2;
delete down2;
delete disable2;
ToolBar::MakeAlternateImages(button, idx,
bmpRecoloredUpLarge, bmpRecoloredDownLarge, bmpRecoloredHiliteLarge,
eEnabledUp, eEnabledDown, eDisabled,
theTheme.ImageSize( bmpRecoloredUpLarge ));
}
void ControlToolBar::Populate()
@@ -180,8 +148,10 @@ void ControlToolBar::Populate()
mPlay = MakeButton( bmpPlay, bmpPlay, bmpPlayDisabled,
ID_PLAY_BUTTON, true, _("Play"));
MakeLoopImage();
MakeAlternateImages(*mPlay, 1, bmpLoop, bmpLoop, bmpLoopDisabled);
MakeAlternateImages(*mPlay, 2,
bmpCutPreview, bmpCutPreview, bmpCutPreviewDisabled);
mPlay->FollowModifierKeys();
mStop = MakeButton( bmpStop, bmpStop, bmpStopDisabled ,
ID_STOP_BUTTON, false, _("Stop"));
@@ -194,6 +164,9 @@ void ControlToolBar::Populate()
mRecord = MakeButton(bmpRecord, bmpRecord, bmpRecordDisabled,
ID_RECORD_BUTTON, true, _("Record"));
MakeAlternateImages(*mRecord, 1, bmpAppendRecord, bmpAppendRecord,
bmpAppendRecordDisabled);
mRecord->FollowModifierKeys();
#if wxUSE_TOOLTIPS
RegenerateToolsTooltips();
@@ -397,7 +370,13 @@ void ControlToolBar::EnableDisableButtons()
}
}
mPlay->SetEnabled((!recording) || (tracks && !busy));
const bool enablePlay = (!recording) || (tracks && !busy);
mPlay->SetEnabled(enablePlay);
// Enable and disable the other play button
TranscriptionToolBar *const pttb = p->GetTranscriptionToolBar();
if (pttb)
pttb->SetEnabled(enablePlay);
mRecord->SetEnabled(!busy && !playing);
mStop->SetEnabled(busy);
@@ -406,14 +385,26 @@ void ControlToolBar::EnableDisableButtons()
mPause->SetEnabled(true);
}
void ControlToolBar::SetPlay(bool down, bool looped)
void ControlToolBar::SetPlay(bool down, bool looped, bool cutPreview)
{
AudacityProject *p = GetActiveProject();
TranscriptionToolBar *const pttb =
p ? p->GetTranscriptionToolBar(): 0;
if (down) {
mPlay->SetAlternate(looped);
mPlay->SetAlternateIdx(cutPreview ? 2 : looped ? 1 : 0);
mPlay->PushDown();
} else {
if (pttb)
// This disables cursor changes for modifier keys
// in the other play button too
pttb->SetPlaying(true, looped, cutPreview);
}
else {
mPlay->PopUp();
mPlay->SetAlternate(false);
mPlay->SetAlternateIdx(0);
if (pttb)
// This reenables cursor changes for modifier keys
// in the other play button too
pttb->SetPlaying(false, looped, cutPreview);
}
EnableDisableButtons();
}
@@ -444,13 +435,12 @@ bool ControlToolBar::IsRecordDown()
{
return mRecord->IsDown();
}
void ControlToolBar::PlayPlayRegion(double t0, double t1,
bool looped /* = false */,
bool cutpreview /* = false */,
TimeTrack *timetrack /* = NULL */)
{
SetPlay(true, looped);
SetPlay(true, looped, cutpreview);
if (gAudioIO->IsBusy()) {
SetPlay(false);
@@ -573,7 +563,7 @@ void ControlToolBar::PlayPlayRegion(double t0, double t1,
#ifdef EXPERIMENTAL_MIDI_OUT
NoteTrackArray(),
#endif
NULL, p->GetRate(), tcp0, tcp1, p, false,
timetrack, p->GetRate(), tcp0, tcp1, p, false,
t0, t1-t0);
} else
{
@@ -677,48 +667,6 @@ void ControlToolBar::OnKeyEvent(wxKeyEvent & event)
event.Skip();
}
void ControlToolBar::OnKeyDown(wxKeyEvent & event)
{
event.Skip();
if (event.GetKeyCode() == WXK_SHIFT)
{
// Turn the "Play" button into a "Loop" button
if (!mPlay->IsDown())
mPlay->SetAlternate(true);
mShiftKeyTimer.Start(100);
}
}
void ControlToolBar::OnKeyUp(wxKeyEvent & event)
{
event.Skip();
if (event.GetKeyCode() == WXK_SHIFT)
{
// Turn the "Loop" button into a "Play" button
if (!mPlay->IsDown())
mPlay->SetAlternate(false);
}
}
void ControlToolBar::OnTimer(wxTimerEvent & event)
{
event.Skip();
// bug 307 fix:
// Shift key-up events get swallowed if a command with a Shift in its keyboard
// shortcut opens a dialog, and ControlToolBar::OnKeyUp() doesn't get called.
if (!wxGetKeyState(WXK_SHIFT))
{
wxKeyEvent dummyEvent;
dummyEvent.m_keyCode = WXK_SHIFT;
this->OnKeyUp(dummyEvent);
mShiftKeyTimer.Stop();
}
}
void ControlToolBar::OnPlay(wxCommandEvent & WXUNUSED(evt))
{
StopPlaying();
@@ -736,12 +684,11 @@ void ControlToolBar::OnStop(wxCommandEvent & WXUNUSED(evt))
void ControlToolBar::PlayDefault()
{
if(mPlay->WasControlDown())
PlayCurrentRegion(false, true); /* play with cut preview */
else if(mPlay->WasShiftDown())
PlayCurrentRegion(true); /* play looped */
else
PlayCurrentRegion(false); /* play normal */
// Let control have precedence over shift
const bool cutPreview = mPlay->WasControlDown();
const bool looped = !cutPreview &&
mPlay->WasShiftDown();
PlayCurrentRegion(looped, cutPreview);
}
void ControlToolBar::StopPlaying(bool stopStream /* = true*/)

View File

@@ -14,8 +14,6 @@
#ifndef __AUDACITY_CONTROL_TOOLBAR__
#define __AUDACITY_CONTROL_TOOLBAR__
#include <wx/timer.h>
#include "ToolBar.h"
#include "../Theme.h"
@@ -44,10 +42,6 @@ class ControlToolBar:public ToolBar {
void UpdatePrefs();
virtual void OnKeyEvent(wxKeyEvent & event);
void OnKeyDown(wxKeyEvent & event);
void OnKeyUp(wxKeyEvent & event);
void OnTimer(wxTimerEvent & event);
// msmeyer: These are public, but it's far better to
// call the "real" interface functions like PlayCurrentRegion() and
@@ -60,7 +54,7 @@ class ControlToolBar:public ToolBar {
void OnPause(wxCommandEvent & evt);
//These allow buttons to be controlled externally:
void SetPlay(bool down, bool looped=false);
void SetPlay(bool down, bool looped=false, bool cutPreview = false);
void SetStop(bool down);
void SetRecord(bool down);
@@ -94,7 +88,13 @@ class ControlToolBar:public ToolBar {
int id,
bool processdownevents,
const wxChar *label);
void MakeLoopImage();
static
void MakeAlternateImages(AButton &button, int idx,
teBmps eEnabledUp,
teBmps eEnabledDown,
teBmps eDisabled);
void ArrangeButtons();
void SetupCutPreviewTracks(double playStart, double cutStart,
double cutEnd, double playEnd);
@@ -118,8 +118,6 @@ class ControlToolBar:public ToolBar {
AButton *mStop;
AButton *mFF;
wxTimer mShiftKeyTimer;
static AudacityProject *mBusyProject;
// Maybe button state values shouldn't be duplicated in this toolbar?

View File

@@ -503,22 +503,40 @@ AButton * ToolBar::MakeButton(teBmps eUp,
int xoff = (size.GetWidth() - theTheme.Image(eStandardUp).GetWidth())/2;
int yoff = (size.GetHeight() - theTheme.Image(eStandardUp).GetHeight())/2;
wxImage * up2 = OverlayImage(eUp, eStandardUp, xoff, yoff);
wxImage * hilite2 = OverlayImage(eHilite, eStandardUp, xoff, yoff);
wxImage * down2 = OverlayImage(eDown, eStandardDown, xoff + 1, yoff + 1);
wxImage * disable2 = OverlayImage(eUp, eDisabled, xoff, yoff);
typedef std::auto_ptr<wxImage> wxImagePtr;
wxImagePtr up2 (OverlayImage(eUp, eStandardUp, xoff, yoff));
wxImagePtr hilite2 (OverlayImage(eHilite, eStandardUp, xoff, yoff));
wxImagePtr down2 (OverlayImage(eDown, eStandardDown, xoff + 1, yoff + 1));
wxImagePtr disable2 (OverlayImage(eUp, eDisabled, xoff, yoff));
AButton * button =
new AButton(this, id, placement, size, *up2, *hilite2, *down2,
*disable2, processdownevents);
delete up2;
delete down2;
delete hilite2;
delete disable2;
return button;
}
//static
void ToolBar::MakeAlternateImages(AButton &button, int idx,
teBmps eUp,
teBmps eDown,
teBmps eHilite,
teBmps eStandardUp,
teBmps eStandardDown,
teBmps eDisabled,
wxSize size)
{
int xoff = (size.GetWidth() - theTheme.Image(eStandardUp).GetWidth())/2;
int yoff = (size.GetHeight() - theTheme.Image(eStandardUp).GetHeight())/2;
typedef std::auto_ptr<wxImage> wxImagePtr;
wxImagePtr up (OverlayImage(eUp, eStandardUp, xoff, yoff));
wxImagePtr hilite (OverlayImage(eHilite, eStandardUp, xoff, yoff));
wxImagePtr down (OverlayImage(eDown, eStandardDown, xoff + 1, yoff + 1));
wxImagePtr disable (OverlayImage(eUp, eDisabled, xoff, yoff));
button.SetAlternateImages(idx, *up, *hilite, *down, *disable);
}
//
// This changes the state a button (from up to down or vice versa)

View File

@@ -127,6 +127,16 @@ class ToolBar:public wxPanel
bool processdownevents,
wxSize size);
static
void MakeAlternateImages(AButton &button, int idx,
teBmps eUp,
teBmps eDown,
teBmps eHilite,
teBmps eStandardUp,
teBmps eStandardDown,
teBmps eDisabled,
wxSize size);
void SetButton(bool down, AButton *button);
void MakeMacRecoloredImage(teBmps eBmpOut, teBmps eBmpIn);

View File

@@ -162,6 +162,16 @@ AButton *TranscriptionToolBar::AddButton(
return r;
}
void TranscriptionToolBar::MakeAlternateImages(
teBmps eFore, teBmps eDisabled,
int id, unsigned altIdx)
{
ToolBar::MakeAlternateImages(*mButtons[id], altIdx,
bmpRecoloredUpSmall, bmpRecoloredDownSmall, bmpRecoloredHiliteSmall,
eFore, eFore, eDisabled,
theTheme.ImageSize( bmpRecoloredUpSmall ));
}
void TranscriptionToolBar::Populate()
{
// Very similar to code in ControlToolBar...
@@ -170,6 +180,9 @@ void TranscriptionToolBar::Populate()
AddButton(bmpPlay, bmpPlayDisabled, TTB_PlaySpeed,
_("Play at selected speed"));
MakeAlternateImages(bmpLoop, bmpLoopDisabled, TTB_PlaySpeed, 1);
MakeAlternateImages(bmpCutPreview, bmpCutPreviewDisabled, TTB_PlaySpeed, 2);
mButtons[TTB_PlaySpeed]->FollowModifierKeys();
//Add a slider that controls the speed of playback.
const int SliderWidth=100;
@@ -386,7 +399,8 @@ void TranscriptionToolBar::GetSamples(WaveTrack *t, sampleCount *s0, sampleCount
*slen = ss1 - ss0;
}
void TranscriptionToolBar::OnPlaySpeed(wxCommandEvent & WXUNUSED(event))
// Come here from button clicks, or commands
void TranscriptionToolBar::PlayAtSpeed(bool looped, bool cutPreview)
{
// Can't do anything without an active project
AudacityProject * p = GetActiveProject();
@@ -427,12 +441,22 @@ void TranscriptionToolBar::OnPlaySpeed(wxCommandEvent & WXUNUSED(event))
#endif
p->GetControlToolBar()->PlayPlayRegion(playRegionStart,
playRegionEnd,
false,
false,
looped,
cutPreview,
mTimeTrack);
}
}
// Come here from button clicks only
void TranscriptionToolBar::OnPlaySpeed(wxCommandEvent & WXUNUSED(event))
{
// Let control have precedence over shift
const bool cutPreview = mButtons[TTB_PlaySpeed]->WasControlDown();
const bool looped = !cutPreview &&
mButtons[TTB_PlaySpeed]->WasShiftDown();
PlayAtSpeed(looped, cutPreview);
}
void TranscriptionToolBar::OnSpeedSlider(wxCommandEvent& WXUNUSED(event))
{
mPlaySpeed = (mPlaySpeedSlider->Get()) * 100;
@@ -867,12 +891,6 @@ void TranscriptionToolBar::SetKeyType(wxCommandEvent & WXUNUSED(event))
}
void TranscriptionToolBar::PlayAtSpeed()
{
wxCommandEvent e;
OnPlaySpeed(e);
}
void TranscriptionToolBar::ShowPlaySpeedDialog()
{
mPlaySpeedSlider->ShowDialog();
@@ -881,6 +899,24 @@ void TranscriptionToolBar::ShowPlaySpeedDialog()
OnSpeedSlider(e);
}
void TranscriptionToolBar::SetEnabled(bool enabled)
{
mButtons[TTB_PlaySpeed]->SetEnabled(enabled);
}
void TranscriptionToolBar::SetPlaying(bool down, bool looped, bool cutPreview)
{
AButton *const button = mButtons[TTB_PlaySpeed];
if (down) {
button->SetAlternateIdx(cutPreview ? 2 : looped ? 1 : 0);
button->PushDown();
}
else {
button->SetAlternateIdx(0);
button->PopUp();
}
}
void TranscriptionToolBar::AdjustPlaySpeed(float adj)
{
if (adj < 0) {

View File

@@ -92,10 +92,13 @@ class TranscriptionToolBar:public ToolBar {
virtual double GetSensitivity();
virtual void SetKeyType(wxCommandEvent & event);
void PlayAtSpeed();
void PlayAtSpeed(bool looped, bool cutPreview);
void ShowPlaySpeedDialog();
void AdjustPlaySpeed(float adj);
void SetEnabled(bool enabled);
void SetPlaying(bool down, bool looped, bool cutPreview);
private:
void InitializeTranscriptionToolBar();
@@ -103,6 +106,9 @@ class TranscriptionToolBar:public ToolBar {
teBmps eFore, teBmps eDisabled,
int id,
const wxChar *label);
void MakeAlternateImages(
teBmps eFore, teBmps eDisabled,
int id, unsigned altIdx);
void GetSamples(WaveTrack *t, sampleCount *s0, sampleCount *slen);
void SetButton(bool newstate, AButton *button);
void RegenerateTooltips();