diff --git a/src/engine/controls/cuecontrol.cpp b/src/engine/controls/cuecontrol.cpp index e0b4f602a3a..039b0193266 100644 --- a/src/engine/controls/cuecontrol.cpp +++ b/src/engine/controls/cuecontrol.cpp @@ -769,8 +769,13 @@ void CueControl::hotcueGotoAndStop(HotcueControl* pControl, double value) { if (pCue) { double position = pCue->getPosition(); if (position != Cue::kNoPosition) { - m_pPlay->set(0.0); - seekExact(position); + if (!m_iCurrentlyPreviewingHotcues && !m_bPreviewing) { + m_pPlay->set(0.0); + seekExact(position); + } else { + // this becomes a play latch command if we are previewing + m_pPlay->set(0.0); + } } } } @@ -861,7 +866,7 @@ void CueControl::hotcueActivatePreview(HotcueControl* pControl, double value) { CuePointer pCue(pControl->getCue()); if (value > 0) { - if (pCue && pCue->getPosition() != Cue::kNoPosition) { + if (pCue && pCue->getPosition() != Cue::kNoPosition && !pControl->isPreviewing()) { m_iCurrentlyPreviewingHotcues++; double position = pCue->getPosition(); m_bypassCueSetByPlay = true; @@ -1026,23 +1031,26 @@ void CueControl::cueGotoAndStop(double value) { return; } - QMutexLocker lock(&m_mutex); - m_pPlay->set(0.0); - double cuePoint = m_pCuePoint->get(); - - // Need to unlock before emitting any signals to prevent deadlock. - lock.unlock(); - - seekExact(cuePoint); + if (!m_iCurrentlyPreviewingHotcues && !m_bPreviewing) { + m_pPlay->set(0.0); + double position = m_pCuePoint->get(); + seekExact(position); + } else { + // this becomes a play latch command if we are previewing + m_pPlay->set(0.0); + } } void CueControl::cuePreview(double value) { + //qDebug() << "CueControl::cuePreview" << value; QMutexLocker lock(&m_mutex); if (value > 0) { - m_bPreviewing = true; - m_bypassCueSetByPlay = true; - m_pPlay->set(1.0); + if (!m_bPreviewing) { + m_bPreviewing = true; + m_bypassCueSetByPlay = true; + m_pPlay->set(1.0); + } } else if (m_bPreviewing) { m_bPreviewing = false; if (m_iCurrentlyPreviewingHotcues) { @@ -1071,7 +1079,10 @@ void CueControl::cueCDJ(double value) { TrackAt trackAt = getTrackAt(); if (value > 0) { - if (m_iCurrentlyPreviewingHotcues) { + if (m_bPreviewing) { + // already previewing, do nothing + return; + } else if (m_iCurrentlyPreviewingHotcues) { // we are already previewing by hotcues // just jump to cue point and continue previewing m_bPreviewing = true; @@ -1095,9 +1106,6 @@ void CueControl::cueCDJ(double value) { } else { // Pause not at cue point and not at end position cueSet(value); - // Just in case. - m_bPreviewing = false; - m_pPlay->set(0.0); // If quantize is enabled, jump to the cue point since it's not // necessarily where we currently are @@ -1138,7 +1146,10 @@ void CueControl::cueDenon(double value) { TrackAt trackAt = getTrackAt(); if (value > 0) { - if (m_iCurrentlyPreviewingHotcues) { + if (m_bPreviewing) { + // already previewing, do nothing + return; + } else if (m_iCurrentlyPreviewingHotcues) { // we are already previewing by hotcues // just jump to cue point and continue previewing m_bPreviewing = true; @@ -1149,13 +1160,8 @@ void CueControl::cueDenon(double value) { m_bPreviewing = true; m_pPlay->set(1.0); } else { - // Just in case. - m_bPreviewing = false; - m_pPlay->set(0.0); - // Need to unlock before emitting any signals to prevent deadlock. lock.unlock(); - seekAbs(m_pCuePoint->get()); } } else if (m_bPreviewing) { diff --git a/src/skin/tooltips.cpp b/src/skin/tooltips.cpp index 87cbd48918e..2a03503e216 100644 --- a/src/skin/tooltips.cpp +++ b/src/skin/tooltips.cpp @@ -468,16 +468,19 @@ void Tooltips::addStandardTooltips() { QString whilePlaying = tr("(while playing)"); QString whileStopped = tr("(while stopped)"); + QString whilePreviewing = tr("(while previewing)"); QString cueSet = tr("Places a cue point at the current position on the waveform."); QString cueWhilePlaying = tr("Stops track at cue point, OR go to cue point and play after release (CUP mode)."); QString cueWhileStopped = tr("Set cue point (Pioneer/Mixxx/Numark mode), set cue point and play after release (CUP mode) " "OR preview from it (Denon mode)."); QString cueHint = tr("Hint: Change the default cue mode in Preferences -> Interface."); + QString latchingPlay = tr("Is latching the playing state."); // Currently used for decks add("play_cue_set") << tr("Play/Pause") << QString("%1: %2").arg(leftClick, tr("Plays or pauses the track.")) + << QString("%1 %2: %3").arg(leftClick, whilePreviewing, latchingPlay) << QString("%1: %2").arg(rightClick, cueSet); // Currently used for minimal decks @@ -494,7 +497,8 @@ void Tooltips::addStandardTooltips() { << QString("%1 %2: %3").arg(leftClick, whileStopped, cueWhileStopped) << cueHint << quantizeSnap - << QString("%1: %2").arg(rightClick, tr("Seeks the track to the cue point and stops.")); + << QString("%1: %2").arg(rightClick, tr("Seeks the track to the cue point and stops.")) + << QString("%1 %2: %3").arg(rightClick, whilePreviewing, latchingPlay); add("cue_gotoandplay_cue_default") << tr("Play") << QString("%1: %2").arg(leftClick, tr("Plays track from the cue point.")) diff --git a/src/widget/whotcuebutton.cpp b/src/widget/whotcuebutton.cpp index 667984c40e4..c78b131c6c7 100644 --- a/src/widget/whotcuebutton.cpp +++ b/src/widget/whotcuebutton.cpp @@ -83,6 +83,12 @@ void WHotcueButton::setup(const QDomNode& node, const SkinContext& context) { void WHotcueButton::mousePressEvent(QMouseEvent* e) { const bool rightClick = e->button() == Qt::RightButton; if (rightClick) { + if (isPressed()) { + // Discard right clicks when already left clicked. + // Otherwise the pop up menu receives the release event and the + // button stucks in the pressed stage. + return; + } if (readDisplayValue() == 1) { // hot cue is set TrackPointer pTrack = PlayerInfo::instance().getTrackInfo(m_group); @@ -116,6 +122,15 @@ void WHotcueButton::mousePressEvent(QMouseEvent* e) { WPushButton::mousePressEvent(e); } +void WHotcueButton::mouseReleaseEvent(QMouseEvent* e) { + const bool rightClick = e->button() == Qt::RightButton; + if (rightClick) { + // Don't handle stray release events + return; + } + WPushButton::mouseReleaseEvent(e); +} + ConfigKey WHotcueButton::createConfigKey(const QString& name) { ConfigKey key; key.group = m_group; diff --git a/src/widget/whotcuebutton.h b/src/widget/whotcuebutton.h index d7a3d218d48..1f3ecd7bdbc 100644 --- a/src/widget/whotcuebutton.h +++ b/src/widget/whotcuebutton.h @@ -21,6 +21,7 @@ class WHotcueButton : public WPushButton { protected: void mousePressEvent(QMouseEvent* e) override; + void mouseReleaseEvent(QMouseEvent* e) override; void restyleAndRepaint() override; private slots: diff --git a/src/widget/wpushbutton.cpp b/src/widget/wpushbutton.cpp index 3965b751230..099ad40429c 100644 --- a/src/widget/wpushbutton.cpp +++ b/src/widget/wpushbutton.cpp @@ -439,6 +439,20 @@ bool WPushButton::event(QEvent* e) { m_bHovered = true; restyleAndRepaint(); } else if (e->type() == QEvent::Leave) { + if (m_bPressed) { + // A Leave event is send instead of a mouseReleaseEvent() + // fake it to get not stucked in pressed state + QMouseEvent mouseEvent = QMouseEvent( + QEvent::MouseButtonRelease, + QPointF(), + QPointF(), + QPointF(), + Qt::LeftButton, + Qt::NoButton, + 0, + Qt::MouseEventSynthesizedByApplication); + mouseReleaseEvent(&mouseEvent); + } m_bHovered = false; restyleAndRepaint(); }