diff --git a/src/notation/internal/notationactioncontroller.cpp b/src/notation/internal/notationactioncontroller.cpp index c1ffb1288f8f6..071c90048c8f2 100644 --- a/src/notation/internal/notationactioncontroller.cpp +++ b/src/notation/internal/notationactioncontroller.cpp @@ -27,6 +27,7 @@ #include "engraving/dom/note.h" #include "engraving/dom/text.h" +#include "engraving/playback/playbackmodel.h" #include "translation.h" #include "log.h" @@ -977,6 +978,33 @@ void NotationActionController::move(MoveDirection direction, bool quickly) return; } + if (playbackController()->isPlaying()) { + MeasureBeat beat = playbackController()->currentBeat(); + int targetBeatIdx = beat.beatIndex; + int targetMeasureIdx = beat.measureIndex; + int increment = (direction == MoveDirection::Right ? 1 : -1); + + const engraving::RepeatList& rl = currentMasterNotation()->masterScore()->repeatList(true); + + if (quickly) { + targetBeatIdx = 0; + targetMeasureIdx += increment; + } else { + targetBeatIdx += increment; + if (targetBeatIdx > beat.maxBeatIndex) { + targetBeatIdx = 0; + targetMeasureIdx += 1; + } else if (targetBeatIdx < 0) { + targetBeatIdx = beat.maxBeatIndex; + targetMeasureIdx -= 1; + } + } + int targetTick = currentMasterNotation()->playback()->beatToTick(targetMeasureIdx, targetBeatIdx); + double targetSec = rl.utick2utime(rl.tick2utick(targetTick)); + playbackController()->seek(targetSec); + break; + } + if (selectedElement && selectedElement->isTextBase()) { interaction->nudge(direction, quickly); } else { diff --git a/src/playback/internal/playbackcontroller.h b/src/playback/internal/playbackcontroller.h index 7e6c103f25c49..db4bb786c95c4 100644 --- a/src/playback/internal/playbackcontroller.h +++ b/src/playback/internal/playbackcontroller.h @@ -117,6 +117,7 @@ class PlaybackController : public IPlaybackController, public muse::actions::Act bool canReceiveAction(const muse::actions::ActionCode& code) const override; + void seek(const muse::audio::secs_t secs) override; private: muse::audio::IPlayerPtr currentPlayer() const; @@ -131,7 +132,6 @@ class PlaybackController : public IPlaybackController, public muse::actions::Act void updateCurrentTempo(); void seek(const muse::midi::tick_t tick); - void seek(const muse::audio::secs_t secs); bool isPaused() const; bool isLoaded() const; diff --git a/src/playback/iplaybackcontroller.h b/src/playback/iplaybackcontroller.h index d358734a57a29..cc09dca0ab292 100644 --- a/src/playback/iplaybackcontroller.h +++ b/src/playback/iplaybackcontroller.h @@ -100,6 +100,8 @@ class IPlaybackController : MODULE_EXPORT_INTERFACE virtual void setNotation(notation::INotationPtr notation) = 0; virtual void setIsExportingAudio(bool exporting) = 0; + + virtual void seek(const muse::audio::secs_t secs) = 0; }; } diff --git a/src/playback/tests/mocks/playbackcontrollermock.h b/src/playback/tests/mocks/playbackcontrollermock.h index e6592025dbca9..0972e8881dee4 100644 --- a/src/playback/tests/mocks/playbackcontrollermock.h +++ b/src/playback/tests/mocks/playbackcontrollermock.h @@ -86,6 +86,8 @@ class PlaybackControllerMock : public IPlaybackController MOCK_METHOD(void, setNotation, (notation::INotationPtr), (override)); MOCK_METHOD(void, setIsExportingAudio, (bool), (override)); + + MOCK_METHOD(void, seek, (const muse::audio::secs_t), (override)); }; }