Introducing modes of Metronome synchronicity

This commit is contained in:
Bruno Herbelin
2021-11-24 21:48:51 +01:00
parent a8abd52afb
commit e123d139e4
7 changed files with 60 additions and 11 deletions

2
.gitignore vendored
View File

@@ -24,3 +24,5 @@ osx/.DS_Store
.DS_Store
osx/runvimix
*.autosave

View File

@@ -51,7 +51,7 @@ MediaPlayer::MediaPlayer()
failed_ = false;
pending_ = false;
metro_linked_ = false;
metro_sync_ = Metronome::SYNC_NONE;
force_update_ = false;
seeking_ = false;
rewind_on_disable_ = false;
@@ -646,7 +646,7 @@ void MediaPlayer::play(bool on)
return;
// Metronome
if (metro_linked_) {
if (metro_sync_) {
// busy with this play()
pending_ = true;
// Execute: sync to Metronome if active
@@ -701,7 +701,7 @@ void MediaPlayer::rewind(bool force)
GstClockTime target = (rate_ > 0.0) ? timeline_.next(0) : timeline_.previous(timeline_.last());
// Metronome
if (metro_linked_) {
if (metro_sync_) {
// busy with this play()
pending_ = true;
// Execute: sync to Metronome if active
@@ -728,7 +728,7 @@ void MediaPlayer::step()
GstEvent *stepevent = gst_event_new_step (GST_FORMAT_BUFFERS, 1, ABS(rate_), TRUE, FALSE);
// Metronome
if (metro_linked_) {
if (metro_sync_) {
// busy with this play()
pending_ = true;
// Execute: sync to Metronome if active

View File

@@ -12,6 +12,7 @@
#include <gst/app/gstappsink.h>
#include "Timeline.h"
#include "Metronome.h"
// Forward declare classes referenced
class Visitor;
@@ -264,6 +265,11 @@ public:
* */
inline void setRewindOnDisabled(bool on) { rewind_on_disable_ = on; }
inline bool rewindOnDisabled() const { return rewind_on_disable_; }
/**
* Option to synchronize with metronome
* */
inline void setSyncToMetronome(Metronome::Synchronicity s) { metro_sync_ = s; }
inline Metronome::Synchronicity synchedToMetronome() const { return metro_sync_; }
/**
* Accept visitors
* */
@@ -307,7 +313,7 @@ private:
bool rewind_on_disable_;
bool force_software_decoding_;
std::string decoder_name_;
bool metro_linked_;
Metronome::Synchronicity metro_sync_;
// fps counter
struct TimeCounter {

View File

@@ -72,6 +72,13 @@ namespace ableton
return sessionState.phaseAtTime(now(), mQuantum);
}
std::chrono::microseconds timeNextPhase() const
{
auto sessionState = mLink.captureAppSessionState();
double beat = ceil(sessionState.phaseAtTime(now(), mQuantum));
return sessionState.timeAtBeat(beat, mQuantum);
}
double tempo() const
{
auto sessionState = mLink.captureAppSessionState();
@@ -218,6 +225,11 @@ std::chrono::microseconds Metronome::timeToBeat()
return engine_.timeNextBeat() - engine_.now();
}
std::chrono::microseconds Metronome::timeToPhase()
{
return engine_.timeNextPhase() - engine_.now();
}
void delay(std::function<void()> f, std::chrono::microseconds us)
{
std::this_thread::sleep_for(us);
@@ -229,6 +241,11 @@ void Metronome::executeAtBeat( std::function<void()> f )
std::thread( delay, f, timeToBeat() ).detach();
}
void Metronome::executeAtPhase( std::function<void()> f )
{
std::thread( delay, f, timeToPhase() ).detach();
}
size_t Metronome::peers() const
{
return link_.numPeers();

View File

@@ -2,7 +2,6 @@
#define METRONOME_H
#include <chrono>
#include <thread>
#include <functional>
class Metronome
@@ -14,6 +13,12 @@ class Metronome
public:
typedef enum {
SYNC_NONE = 0,
SYNC_BEAT,
SYNC_PHASE
} Synchronicity;
static Metronome& manager ()
{
// The only instance
@@ -41,10 +46,14 @@ public:
double beats () const;
double phase () const;
// mechanisms to delay execution to next beat of phase
// mechanisms to delay execution to next beat
std::chrono::microseconds timeToBeat();
void executeAtBeat( std::function<void()> f );
// mechanisms to delay execution to next phase
std::chrono::microseconds timeToPhase();
void executeAtPhase( std::function<void()> f );
size_t peers () const;
};

View File

@@ -2470,13 +2470,28 @@ void SourceController::Render()
if (ImGui::MenuItem(LABEL_EDIT_FADING))
mediaplayer_edit_fading_ = true;
if (ImGui::BeginMenu(ICON_FA_SNOWFLAKE " Inactive action"))
if (ImGui::BeginMenu(ICON_FA_CLOCK " Metronome"))
{
Metronome::Synchronicity sync = mediaplayer_active_->synchedToMetronome();
bool active = sync == Metronome::SYNC_NONE;
if (ImGuiToolkit::MenuItemIcon(5, 13, " Not synchronized", active ))
mediaplayer_active_->setSyncToMetronome(Metronome::SYNC_NONE);
active = sync == Metronome::SYNC_BEAT;
if (ImGuiToolkit::MenuItemIcon(6, 13, " Sync to beat", active ))
mediaplayer_active_->setSyncToMetronome(Metronome::SYNC_BEAT);
active = sync == Metronome::SYNC_PHASE;
if (ImGuiToolkit::MenuItemIcon(7, 13, " Sync to phase", active ))
mediaplayer_active_->setSyncToMetronome(Metronome::SYNC_PHASE);
ImGui::EndMenu();
}
if (ImGui::BeginMenu(ICON_FA_SNOWFLAKE " Deactivation"))
{
bool option = !mediaplayer_active_->rewindOnDisabled();
if (ImGui::MenuItem(ICON_FA_STOP " Stop", "", &option ))
if (ImGui::MenuItem(ICON_FA_STOP " Stop", NULL, &option ))
mediaplayer_active_->setRewindOnDisabled(false);
option = mediaplayer_active_->rewindOnDisabled();
if (ImGui::MenuItem(ICON_FA_FAST_BACKWARD " Rewind & Stop", "", &option ))
if (ImGui::MenuItem(ICON_FA_FAST_BACKWARD " Rewind & Stop", NULL, &option ))
mediaplayer_active_->setRewindOnDisabled(true);
ImGui::EndMenu();
}
@@ -4926,7 +4941,7 @@ void Navigator::RenderMainPannelVimix()
Settings::application.widget.timer = !Settings::application.widget.timer;
}
if (ImGui::IsItemHovered())
tooltip_ = "Timer " CTRL_MOD "T";
tooltip_ = "Timer " CTRL_MOD "T";
ImGui::PopFont();
if (!tooltip_.empty()) {

Binary file not shown.