@@ -44,6 +44,7 @@ using namespace mu::notation;
4444using namespace mu ::playback;
4545
4646static const ActionCode PLAY_CODE (" play" );
47+ static const ActionCode PLAY_FROM_SELECTION (" play-from-selection" );
4748static const ActionCode STOP_CODE (" stop" );
4849static const ActionCode PAUSE_AND_SELECT_CODE (" pause-and-select" );
4950static const ActionCode REWIND_CODE (" rewind" );
@@ -91,6 +92,7 @@ static std::string resolveAuxTrackTitle(aux_channel_idx_t index, const AudioOutp
9192void PlaybackController::init ()
9293{
9394 dispatcher ()->reg (this , PLAY_CODE, this , &PlaybackController::togglePlay);
95+ dispatcher ()->reg (this , PLAY_FROM_SELECTION, this , &PlaybackController::playFromSelection);
9496 dispatcher ()->reg (this , STOP_CODE, [this ]() { PlaybackController::pause (/* select*/ false ); });
9597 dispatcher ()->reg (this , PAUSE_AND_SELECT_CODE, [this ]() { PlaybackController::pause (/* select*/ true ); });
9698 dispatcher ()->reg (this , REWIND_CODE, this , &PlaybackController::rewind);
@@ -667,6 +669,44 @@ void PlaybackController::play()
667669 currentPlayer ()->play (delay);
668670}
669671
672+ void PlaybackController::playFromSelection ()
673+ {
674+ const LoopBoundaries& loop = notationPlayback ()->loopBoundaries ();
675+ const int loopInTick = loop.loopInTick .ticks ();
676+ const int loopOutTick = loop.loopOutTick .ticks ();
677+
678+ int minTick = INT_MAX;
679+
680+ for (const EngravingItem* item : selection ()->elements ()) {
681+ const RetVal<midi::tick_t > retval = notationPlayback ()->playPositionTickByElement (item);
682+ if (!retval.ret ) {
683+ continue ;
684+ }
685+
686+ const int tick = static_cast <int >(retval.val );
687+
688+ if (loop.enabled ) {
689+ if (tick < loopInTick || tick > loopOutTick) {
690+ continue ;
691+ }
692+ }
693+
694+ minTick = std::min (minTick, tick);
695+ }
696+
697+ if (minTick == INT_MAX) {
698+ return ;
699+ }
700+
701+ seek (playedTickToSecs (minTick));
702+
703+ if (isPaused ()) {
704+ resume ();
705+ } else if (!isPlaying ()) {
706+ play ();
707+ }
708+ }
709+
670710void PlaybackController::rewind (const ActionData& args)
671711{
672712 secs_t startSecs = playbackStartSecs ();
@@ -1872,9 +1912,18 @@ void PlaybackController::setIsExportingAudio(bool exporting)
18721912 }
18731913}
18741914
1875- bool PlaybackController::canReceiveAction (const ActionCode&) const
1915+ bool PlaybackController::canReceiveAction (const ActionCode& code ) const
18761916{
1877- return m_masterNotation != nullptr && m_masterNotation->hasParts ();
1917+ if (!m_masterNotation || !m_masterNotation->hasParts ()) {
1918+ return false ;
1919+ }
1920+
1921+ if (code == PLAY_FROM_SELECTION) {
1922+ const INotationInteractionPtr interaction = this ->interaction ();
1923+ return interaction && !interaction->selection ()->isNone () && !interaction->isElementEditStarted ();
1924+ }
1925+
1926+ return true ;
18781927}
18791928
18801929const std::map<muse::audio::TrackId, muse::audio::AudioResourceMeta>& PlaybackController::onlineSounds () const
0 commit comments