Skip to content

Commit 5784913

Browse files
Add "Play from selection" shortcut
1 parent d530bd3 commit 5784913

File tree

6 files changed

+74
-2
lines changed

6 files changed

+74
-2
lines changed

src/app/configs/data/shortcuts.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -801,6 +801,11 @@
801801
<seq>Space</seq>
802802
<autorepeat>0</autorepeat>
803803
</SC>
804+
<SC>
805+
<key>play-from-selection</key>
806+
<seq>Shift+Space</seq>
807+
<autorepeat>0</autorepeat>
808+
</SC>
804809
<SC>
805810
<key>pause-and-select</key>
806811
<seq>Ctrl+Space</seq>

src/app/configs/data/shortcuts_azerty.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -842,6 +842,11 @@
842842
<seq>Space</seq>
843843
<autorepeat>0</autorepeat>
844844
</SC>
845+
<SC>
846+
<key>play-from-selection</key>
847+
<seq>Shift+Space</seq>
848+
<autorepeat>0</autorepeat>
849+
</SC>
845850
<SC>
846851
<key>pause-and-select</key>
847852
<seq>Ctrl+Space</seq>

src/app/configs/data/shortcuts_mac.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -801,6 +801,11 @@
801801
<seq>Space</seq>
802802
<autorepeat>0</autorepeat>
803803
</SC>
804+
<SC>
805+
<key>play-from-selection</key>
806+
<seq>Shift+Space</seq>
807+
<autorepeat>0</autorepeat>
808+
</SC>
804809
<SC>
805810
<key>pause-and-select</key>
806811
<seq>Alt+Space</seq>

src/playback/internal/playbackcontroller.cpp

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ using namespace mu::notation;
4444
using namespace mu::playback;
4545

4646
static const ActionCode PLAY_CODE("play");
47+
static const ActionCode PLAY_FROM_SELECTION("play-from-selection");
4748
static const ActionCode STOP_CODE("stop");
4849
static const ActionCode PAUSE_AND_SELECT_CODE("pause-and-select");
4950
static const ActionCode REWIND_CODE("rewind");
@@ -91,6 +92,7 @@ static std::string resolveAuxTrackTitle(aux_channel_idx_t index, const AudioOutp
9192
void 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+
670710
void 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

18801929
const std::map<muse::audio::TrackId, muse::audio::AudioResourceMeta>& PlaybackController::onlineSounds() const

src/playback/internal/playbackcontroller.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ class PlaybackController : public IPlaybackController, public muse::actions::Act
167167
void togglePlay();
168168
void rewind(const muse::actions::ActionData& args);
169169
void play();
170+
void playFromSelection();
170171
void pause(bool select = false);
171172
void stop();
172173
void resume();

src/playback/internal/playbackuiactions.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,13 @@ const UiActionList PlaybackUiActions::s_mainActions = {
3939
TranslatableString("action", "Play"),
4040
IconCode::Code::PLAY
4141
),
42+
UiAction("play-from-selection",
43+
mu::context::UiCtxProjectOpened,
44+
mu::context::CTX_NOTATION_OPENED,
45+
TranslatableString("action", "Play from selection"),
46+
TranslatableString("action", "Play from selection"),
47+
IconCode::Code::PLAY
48+
),
4249
UiAction("stop",
4350
mu::context::UiCtxProjectOpened,
4451
mu::context::CTX_NOTATION_OPENED,

0 commit comments

Comments
 (0)