summaryrefslogtreecommitdiff
path: root/gtk2_ardour/tempo_curve.cc
diff options
context:
space:
mode:
authornick_m <mainsbridge@gmail.com>2016-05-08 03:03:12 +1000
committernick_m <mainsbridge@gmail.com>2016-05-27 23:38:16 +1000
commit86b0268e8be554e9286aebd544757fc13fe76dac (patch)
tree959f2fb0dbe33a738e15caf8186a56a58beace56 /gtk2_ardour/tempo_curve.cc
parent652a59b3178b0d0905f8d9610500a71f0924edc0 (diff)
Tempo ramps - add visualtempo curve, dragging bbt or music rulers with constraint modifier dilates previous tempo.
Diffstat (limited to 'gtk2_ardour/tempo_curve.cc')
-rw-r--r--gtk2_ardour/tempo_curve.cc194
1 files changed, 194 insertions, 0 deletions
diff --git a/gtk2_ardour/tempo_curve.cc b/gtk2_ardour/tempo_curve.cc
new file mode 100644
index 0000000000..b340ee0145
--- /dev/null
+++ b/gtk2_ardour/tempo_curve.cc
@@ -0,0 +1,194 @@
+#include <sigc++/bind.h>
+#include "ardour/tempo.h"
+
+#include "canvas/rectangle.h"
+#include "canvas/container.h"
+#include "canvas/curve.h"
+#include "canvas/polygon.h"
+#include "canvas/canvas.h"
+#include "canvas/debug.h"
+
+#include "ui_config.h"
+
+#include "tempo_curve.h"
+#include "public_editor.h"
+#include "utils.h"
+#include "rgb_macros.h"
+
+#include <gtkmm2ext/utils.h>
+
+#include "i18n.h"
+
+PBD::Signal1<void,TempoCurve*> TempoCurve::CatchDeletion;
+
+TempoCurve::TempoCurve (PublicEditor& ed, ArdourCanvas::Container& parent, guint32 rgba, ARDOUR::TempoSection& temp, framepos_t frame, bool handle_events)
+
+ : editor (ed)
+ , _parent (&parent)
+ , _shown (false)
+ , _curve (0)
+ , _color (rgba)
+ , _max_tempo (temp.beats_per_minute())
+ , _tempo (temp)
+
+
+{
+ const double MH = 12.0;
+ const double M3 = std::max(1.f, rintf(3.f * UIConfiguration::instance().get_ui_scale()));
+ const double M6 = std::max(2.f, rintf(6.f * UIConfiguration::instance().get_ui_scale()));
+
+ points = new ArdourCanvas::Points ();
+ points->push_back (ArdourCanvas::Duple (0.0, 0.0));
+ points->push_back (ArdourCanvas::Duple (1.0, 0.0));
+ points->push_back (ArdourCanvas::Duple (1.0, MH));
+ points->push_back (ArdourCanvas::Duple (0.0, MH));
+
+ frame_position = frame;
+ unit_position = editor.sample_to_pixel (frame);
+
+ group = new ArdourCanvas::Container (&parent, ArdourCanvas::Duple (unit_position, 0));
+#ifdef CANVAS_DEBUG
+ group->name = string_compose ("Marker::group for %1", _tempo.beats_per_minute());
+#endif
+
+ _background = new ArdourCanvas::Rectangle (group);
+#ifdef CANVAS_DEBUG
+ _background->name = string_compose ("Marker::_background for %1", _tempo.beats_per_minute());
+#endif
+ _background->set_x0 (0.0);
+ _background->set_x1 (ArdourCanvas::COORD_MAX);
+ _background->set_outline_what (ArdourCanvas::Rectangle::What(0));
+ _curve = new ArdourCanvas::Curve (group);
+#ifdef CANVAS_DEBUG
+ _curve->name = string_compose ("Marker::_background for %1", _tempo.beats_per_minute());
+#endif
+ _curve->set_fill_mode (ArdourCanvas::Curve::Inside);
+ _curve->set_points_per_segment (32);
+ _curve->set (*points);
+
+ set_color_rgba (rgba);
+
+ editor.ZoomChanged.connect (sigc::mem_fun (*this, &TempoCurve::reposition));
+
+ /* events will be handled by both the group and the mark itself, so
+ * make sure they can both be used to lookup this object.
+ */
+
+ group->set_data ("marker", this);
+
+ if (handle_events) {
+ //group->Event.connect (sigc::bind (sigc::mem_fun (editor, &PublicEditor::canvas_marker_event), group, this));
+ }
+ set_position (_tempo.frame(), UINT32_MAX);
+ _curve->Event.connect (sigc::bind (sigc::mem_fun (editor, &PublicEditor::canvas_tempo_curve_event), group, this));
+ _background->Event.connect (sigc::bind (sigc::mem_fun (editor, &PublicEditor::canvas_tempo_curve_event), group, this));
+
+}
+
+TempoCurve::~TempoCurve ()
+{
+ CatchDeletion (this); /* EMIT SIGNAL */
+
+ /* destroying the parent group destroys its contents, namely any polygons etc. that we added */
+ delete group;
+}
+
+void TempoCurve::reparent(ArdourCanvas::Container & parent)
+{
+ group->reparent (&parent);
+ _parent = &parent;
+}
+
+void
+TempoCurve::canvas_height_set (double h)
+{
+ _canvas_height = h;
+}
+
+ArdourCanvas::Item&
+TempoCurve::the_item() const
+{
+ return *group;
+}
+
+void
+TempoCurve::set_position (framepos_t frame, framepos_t end_frame)
+{
+ const double height = 12.0;
+ points->clear();
+ unit_position = editor.sample_to_pixel (frame);
+ group->set_x_position (unit_position);
+ frame_position = frame;
+ _end_frame = end_frame;
+ _background->set_x0 (0.0);
+ _background->set_x1 (editor.sample_to_pixel (end_frame - frame));
+ const double tempo_delta = max (10.0, _max_tempo - _min_tempo);
+ double max_y = 0.0;
+ points = new ArdourCanvas::Points ();
+ if (end_frame == UINT32_MAX) {
+ _curve->set_fill_mode (ArdourCanvas::Curve::None);
+ const double tempo_at = _tempo.tempo_at_frame (frame, editor.session()->frame_rate()) * _tempo.note_type();
+ const double y2_pos = (height + 2.0) - (((tempo_at - _min_tempo) / (tempo_delta)) * height);
+ max_y = y2_pos;
+ points->push_back (ArdourCanvas::Duple (0.0, y2_pos));
+ points->push_back (ArdourCanvas::Duple (ArdourCanvas::COORD_MAX - 5.0, y2_pos));
+
+ } else {
+ _curve->set_fill_mode (ArdourCanvas::Curve::Inside);
+ const framepos_t frame_step = (end_frame - frame) / 32;
+ framepos_t current_frame = frame;
+ while (current_frame < end_frame) {
+ const double tempo_at = _tempo.tempo_at_frame (current_frame, editor.session()->frame_rate()) * _tempo.note_type();
+ const double y2_pos = (height + 2.0) - (((tempo_at - _min_tempo) / (tempo_delta)) * height);
+
+ points->push_back (ArdourCanvas::Duple (editor.sample_to_pixel (current_frame - frame), y2_pos));
+ max_y = max (y2_pos, max_y);
+ current_frame += frame_step;
+ }
+ }
+
+ /* the background fills the gap between the bottom of the curve and the time bar */
+ _background->set_y0 (max_y + 1.0);
+ _background->set_y1 (height + 2.0);
+
+ if (max_y == height + 2.0) {
+ _background->hide();
+ } else {
+ _background->show();
+ }
+
+ _curve->set (*points);
+}
+
+void
+TempoCurve::reposition ()
+{
+ set_position (frame_position, _end_frame);
+}
+
+void
+TempoCurve::show ()
+{
+ _shown = true;
+
+ group->show ();
+}
+
+void
+TempoCurve::hide ()
+{
+ _shown = false;
+
+ group->hide ();
+}
+
+void
+TempoCurve::set_color_rgba (uint32_t c)
+{
+ _color = c;
+ _curve->set_fill_color (UIConfiguration::instance().color_mod ("selection rect", "selection rect"));
+ _curve->set_outline_color (_color);
+
+ _background->set_fill (true);
+ _background->set_fill_color (UIConfiguration::instance().color_mod ("selection rect", "selection rect"));
+}