From bf3fc3f92a6dbc5a91e0660c982863fb005d0f16 Mon Sep 17 00:00:00 2001 From: Ben Loftis Date: Fri, 27 Sep 2024 10:10:10 -0500 Subject: [PATCH] Add Transport Clock widgets that reflect the canonical ones in ArdourUI --- gtk2_ardour/ardour_ui.cc | 4 +- gtk2_ardour/audio_clock.h | 3 +- gtk2_ardour/main_clock.cc | 80 ++++++++++++++++++++++++++++++++++++++- gtk2_ardour/main_clock.h | 35 ++++++++++++++++- 4 files changed, 117 insertions(+), 5 deletions(-) diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc index c3d449ea12..6b530d89bc 100644 --- a/gtk2_ardour/ardour_ui.cc +++ b/gtk2_ardour/ardour_ui.cc @@ -282,8 +282,8 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir) : Gtkmm2ext::UI (PROGRAM_NAME, X_("gui"), argcp, argvp) , session_load_in_progress (false) , gui_object_state (new GUIObjectState) - , primary_clock (new MainClock (X_("primary"), X_("transport"))) - , secondary_clock (new MainClock (X_("secondary"), X_("secondary"))) + , primary_clock (new MainClock (X_("primary"), X_("transport"), MainClock::PrimaryClock)) + , secondary_clock (new MainClock (X_("secondary"), X_("secondary"), MainClock::SecondaryClock)) , big_clock (new AudioClock (X_("bigclock"), false, "big", true, true, false, false)) , video_timeline(0) , ignore_dual_punch (false) diff --git a/gtk2_ardour/audio_clock.h b/gtk2_ardour/audio_clock.h index b697c0b123..2c498e1770 100644 --- a/gtk2_ardour/audio_clock.h +++ b/gtk2_ardour/audio_clock.h @@ -76,9 +76,10 @@ public: virtual void set (Temporal::timepos_t const &, bool force = false); void set_duration (Temporal::timecnt_t const &, bool force = false); + virtual void set_mode (Mode); + void set_from_playhead (); void locate (); - void set_mode (Mode); void copy_text_to_clipboard () const; diff --git a/gtk2_ardour/main_clock.cc b/gtk2_ardour/main_clock.cc index 867ac3b59c..a7919e0a23 100644 --- a/gtk2_ardour/main_clock.cc +++ b/gtk2_ardour/main_clock.cc @@ -29,20 +29,29 @@ #include "actions.h" #include "main_clock.h" #include "public_editor.h" +#include "ardour_ui.h" #include "pbd/i18n.h" using namespace Gtk; using namespace ARDOUR; +using namespace std; MainClock::MainClock ( const std::string& clock_name, - const std::string& widget_name + const std::string& widget_name, + ClockDisposition d ) : AudioClock (clock_name, false, widget_name, true, true, false, true) + , _disposition(d) , _suspend_delta_mode_signal (false) , _widget_name(widget_name) { + ValueChanged.connect (sigc::mem_fun(*this, &MainClock::clock_value_changed)); + + UIConfiguration::instance().ParameterChanged.connect (sigc::mem_fun (*this, &MainClock::parameter_changed)); + std::function pc (std::bind (&MainClock::parameter_changed, this, _1)); + UIConfiguration::instance().map_parameters (pc); } void @@ -53,6 +62,24 @@ MainClock::set_session (ARDOUR::Session *s) _right_btn.set_related_action (ActionManager::get_action (X_("Editor"), X_("edit-current-meter"))); } +void +MainClock::parameter_changed (std::string p) +{ + if (p == "primary-clock-delta-mode" && _disposition == PrimaryClock) { + set_display_delta_mode(UIConfiguration::instance().get_primary_clock_delta_mode()); + } else if (p == "secondary-clock-delta-mode" && _disposition == SecondaryClock) { + set_display_delta_mode(UIConfiguration::instance().get_secondary_clock_delta_mode()); + } +} + +void +MainClock::clock_value_changed () +{ + if (_session) { + _session->request_locate (last_when ().samples()); + } +} + void MainClock::build_ops_menu () { @@ -110,6 +137,8 @@ MainClock::set (timepos_t const & when, bool force) } break; } + + CanonicalClockChanged (); //signal } void @@ -159,3 +188,52 @@ MainClock::insert_new_meter () { PublicEditor::instance().mouse_add_new_meter_event (last_when ()); } + + +TransportClock::TransportClock ( + const std::string& clock_name, + const std::string& widget_name, + ClockDisposition d + ) + : MainClock (clock_name, widget_name, d) +{ + if (_disposition==PrimaryClock) { + ARDOUR_UI::instance()->primary_clock->CanonicalClockChanged.connect (sigc::mem_fun(*this, &TransportClock::follow_canonical_clock)); + ARDOUR_UI::instance()->primary_clock->mode_changed.connect (sigc::mem_fun(*this, &TransportClock::follow_canonical_clock)); + change_display_delta_mode_signal.connect (sigc::mem_fun(UIConfiguration::instance(), &UIConfiguration::set_primary_clock_delta_mode)); + } else { + ARDOUR_UI::instance()->secondary_clock->CanonicalClockChanged.connect (sigc::mem_fun(*this, &TransportClock::follow_canonical_clock)); + ARDOUR_UI::instance()->secondary_clock->mode_changed.connect (sigc::mem_fun(*this, &TransportClock::follow_canonical_clock)); + change_display_delta_mode_signal.connect (sigc::mem_fun(UIConfiguration::instance(), &UIConfiguration::set_secondary_clock_delta_mode)); + } +} + +void +TransportClock::set_mode(Mode m) +{ + //we don't set the mode for ourselves; instead we set the canonical clock and then 'follow' it + + if (_disposition==PrimaryClock) { + ARDOUR_UI::instance()->primary_clock->set_mode(m); + } else { + ARDOUR_UI::instance()->secondary_clock->set_mode(m); + } +} + +void +TransportClock::follow_canonical_clock () +{ + if (!_session) { + return; + } + + set(timepos_t(_session->audible_sample())); + + if (_disposition==PrimaryClock) { + AudioClock::set_mode(ARDOUR_UI::instance()->primary_clock->mode()); + set_display_delta_mode(ARDOUR_UI::instance()->primary_clock->display_delta_mode()); + } else { + AudioClock::set_mode(ARDOUR_UI::instance()->secondary_clock->mode()); + set_display_delta_mode(ARDOUR_UI::instance()->secondary_clock->display_delta_mode()); + } +} diff --git a/gtk2_ardour/main_clock.h b/gtk2_ardour/main_clock.h index 3b4ca44715..bc213c9e07 100644 --- a/gtk2_ardour/main_clock.h +++ b/gtk2_ardour/main_clock.h @@ -27,12 +27,29 @@ class MainClock : public AudioClock { public: - MainClock (const std::string& clock_name, const std::string& widget_name); + enum ClockDisposition { + PrimaryClock, + SecondaryClock + }; + + MainClock (const std::string& clock_name, const std::string& widget_name, ClockDisposition d); void set_session (ARDOUR::Session *s); + + ARDOUR::ClockDeltaMode display_delta_mode () {return _delta_mode;} void set_display_delta_mode (ARDOUR::ClockDeltaMode m); + void set (Temporal::timepos_t const &, bool force = false); sigc::signal change_display_delta_mode_signal; + sigc::signal CanonicalClockChanged; + + void clock_value_changed(); + + void parameter_changed (std::string p); + +protected: + ClockDisposition _disposition; + private: void build_ops_menu (); void change_display_delta_mode (ARDOUR::ClockDeltaMode); @@ -45,3 +62,19 @@ private: ARDOUR::ClockDeltaMode _delta_mode; }; +/** TransportClock is a clock widget that reflects the state of the canonical MainClocks in ARDOUR_UI (either Primary or Secondary) + * there are multiple Primary and Secondary clock widgets, but from the user's perspective they all represent the "same clock" + * The current position, display mode, and 'delta mode' are globally shared across Primary and Secondary clocks. + * Other state, such as the editing/text-entry state, remains per-widget. +*/ +class TransportClock : public MainClock +{ +public: + TransportClock (const std::string& clock_name, const std::string& widget_name, ClockDisposition d); + +protected: + void set_mode(Mode); //override + +private: + void follow_canonical_clock(); +};