13
0

Add Transport Clock widgets that reflect the canonical ones in ArdourUI

This commit is contained in:
Ben Loftis 2024-09-27 10:10:10 -05:00 committed by Robin Gareus
parent 1641be9f7a
commit bf3fc3f92a
Signed by: rgareus
GPG Key ID: A090BCE02CF57F04
4 changed files with 117 additions and 5 deletions

View File

@ -282,8 +282,8 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
: Gtkmm2ext::UI (PROGRAM_NAME, X_("gui"), argcp, argvp) : Gtkmm2ext::UI (PROGRAM_NAME, X_("gui"), argcp, argvp)
, session_load_in_progress (false) , session_load_in_progress (false)
, gui_object_state (new GUIObjectState) , gui_object_state (new GUIObjectState)
, primary_clock (new MainClock (X_("primary"), X_("transport"))) , primary_clock (new MainClock (X_("primary"), X_("transport"), MainClock::PrimaryClock))
, secondary_clock (new MainClock (X_("secondary"), X_("secondary"))) , secondary_clock (new MainClock (X_("secondary"), X_("secondary"), MainClock::SecondaryClock))
, big_clock (new AudioClock (X_("bigclock"), false, "big", true, true, false, false)) , big_clock (new AudioClock (X_("bigclock"), false, "big", true, true, false, false))
, video_timeline(0) , video_timeline(0)
, ignore_dual_punch (false) , ignore_dual_punch (false)

View File

@ -76,9 +76,10 @@ public:
virtual void set (Temporal::timepos_t const &, bool force = false); virtual void set (Temporal::timepos_t const &, bool force = false);
void set_duration (Temporal::timecnt_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 set_from_playhead ();
void locate (); void locate ();
void set_mode (Mode);
void copy_text_to_clipboard () const; void copy_text_to_clipboard () const;

View File

@ -29,20 +29,29 @@
#include "actions.h" #include "actions.h"
#include "main_clock.h" #include "main_clock.h"
#include "public_editor.h" #include "public_editor.h"
#include "ardour_ui.h"
#include "pbd/i18n.h" #include "pbd/i18n.h"
using namespace Gtk; using namespace Gtk;
using namespace ARDOUR; using namespace ARDOUR;
using namespace std;
MainClock::MainClock ( MainClock::MainClock (
const std::string& clock_name, 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) : AudioClock (clock_name, false, widget_name, true, true, false, true)
, _disposition(d)
, _suspend_delta_mode_signal (false) , _suspend_delta_mode_signal (false)
, _widget_name(widget_name) , _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<void (std::string)> pc (std::bind (&MainClock::parameter_changed, this, _1));
UIConfiguration::instance().map_parameters (pc);
} }
void 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"))); _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 void
MainClock::build_ops_menu () MainClock::build_ops_menu ()
{ {
@ -110,6 +137,8 @@ MainClock::set (timepos_t const & when, bool force)
} }
break; break;
} }
CanonicalClockChanged (); //signal
} }
void void
@ -159,3 +188,52 @@ MainClock::insert_new_meter ()
{ {
PublicEditor::instance().mouse_add_new_meter_event (last_when ()); 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());
}
}

View File

@ -27,12 +27,29 @@
class MainClock : public AudioClock class MainClock : public AudioClock
{ {
public: 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); void set_session (ARDOUR::Session *s);
ARDOUR::ClockDeltaMode display_delta_mode () {return _delta_mode;}
void set_display_delta_mode (ARDOUR::ClockDeltaMode m); void set_display_delta_mode (ARDOUR::ClockDeltaMode m);
void set (Temporal::timepos_t const &, bool force = false); void set (Temporal::timepos_t const &, bool force = false);
sigc::signal<bool, ARDOUR::ClockDeltaMode> change_display_delta_mode_signal; sigc::signal<bool, ARDOUR::ClockDeltaMode> change_display_delta_mode_signal;
sigc::signal<void> CanonicalClockChanged;
void clock_value_changed();
void parameter_changed (std::string p);
protected:
ClockDisposition _disposition;
private: private:
void build_ops_menu (); void build_ops_menu ();
void change_display_delta_mode (ARDOUR::ClockDeltaMode); void change_display_delta_mode (ARDOUR::ClockDeltaMode);
@ -45,3 +62,19 @@ private:
ARDOUR::ClockDeltaMode _delta_mode; 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();
};