initial (incomplete) framework for DiskIOPoint manipulation
[ardour.git] / gtk2_ardour / audio_clock.cc
index b21d32720177d47b6de6cb4724fca568886ff662..3c5d065264436e4a3f2b0f11de54ac001f185e05 100644 (file)
 #include <gtkmm/style.h>
 #include <sigc++/bind.h>
 
-#include "gtkmm2ext/cairocell.h"
 #include "gtkmm2ext/utils.h"
 #include "gtkmm2ext/rgb_macros.h"
 
+#include "widgets/tooltips.h"
+
 #include "ardour/profile.h"
 #include "ardour/lmath.h"
 #include "ardour/session.h"
@@ -39,9 +40,9 @@
 
 #include "ardour_ui.h"
 #include "audio_clock.h"
+#include "enums_convert.h"
 #include "gui_thread.h"
 #include "keyboard.h"
-#include "tooltips.h"
 #include "ui_config.h"
 #include "utils.h"
 
@@ -49,6 +50,7 @@
 
 using namespace ARDOUR;
 using namespace ARDOUR_UI_UTILS;
+using namespace ArdourWidgets;
 using namespace PBD;
 using namespace Gtk;
 using namespace std;
@@ -76,6 +78,7 @@ AudioClock::AudioClock (const string& clock_name, bool transient, const string&
        , _edit_by_click_field (false)
        , _negative_allowed (false)
        , edit_is_negative (false)
+       , _limit_pos (INT64_MAX - 1)
        , _with_info (with_info)
        , editing_attr (0)
        , foreground_attr (0)
@@ -275,8 +278,9 @@ AudioClock::set_scale (double x, double y)
 }
 
 void
-AudioClock::render (cairo_t* cr, cairo_rectangle_t*)
+AudioClock::render (Cairo::RefPtr<Cairo::Context> const& ctx, cairo_rectangle_t*)
 {
+       cairo_t* cr = ctx->cobj();
        /* main layout: rounded rect, plus the text */
 
        if (_need_bg) {
@@ -324,10 +328,10 @@ AudioClock::render (cairo_t* cr, cairo_rectangle_t*)
 
                                cairo_set_source_rgba (cr, cursor_r, cursor_g, cursor_b, cursor_a);
                                cairo_rectangle (cr,
-                                                min (get_width() - 2.0,
-                                                     (double) xcenter + cursor.get_x()/PANGO_SCALE + em_width),
-                                                (get_height() - layout_height)/2.0,
-                                                2.0, cursor.get_height()/PANGO_SCALE);
+                                                min (get_width() - 2.0,
+                                                (double) xcenter + cursor.get_x()/PANGO_SCALE + em_width),
+                                                (get_height() - layout_height)/2.0,
+                                                2.0, cursor.get_height()/PANGO_SCALE);
                                cairo_fill (cr);
                        } else {
                                /* we've entered all possible digits, no cursor */
@@ -809,7 +813,7 @@ AudioClock::session_configuration_changed (std::string p)
 void
 AudioClock::set (framepos_t when, bool force, framecnt_t offset)
 {
-       if ((!force && !is_visible()) || _session == 0) {
+       if ((!force && !is_visible()) || _session == 0) {
                return;
        }
 
@@ -817,6 +821,12 @@ AudioClock::set (framepos_t when, bool force, framecnt_t offset)
                when = when - offset;
        }
 
+       if (when > _limit_pos) {
+               when = _limit_pos;
+       } else if (when < -_limit_pos) {
+               when = -_limit_pos;
+       }
+
        if (when == last_when && !force) {
 #if 0 // XXX return if no change and no change forced. verify Aug/2014
                if (_mode != Timecode && _mode != MinSec) {
@@ -941,6 +951,24 @@ AudioClock::set_slave_info ()
        }
 }
 
+void
+AudioClock::set_out_of_bounds (bool negative)
+{
+       if (is_duration) {
+               if (negative) {
+                       _layout->set_text (" >>> -- <<< ");
+               } else {
+                       _layout->set_text (" >>> ++ <<< ");
+               }
+       } else {
+               if (negative) {
+                       _layout->set_text (" <<<<<<<<<< ");
+               } else {
+                       _layout->set_text (" >>>>>>>>>> ");
+               }
+       }
+}
+
 void
 AudioClock::set_frames (framepos_t when, bool /*force*/)
 {
@@ -959,14 +987,16 @@ AudioClock::set_frames (framepos_t when, bool /*force*/)
                negative = true;
        }
 
-       if (negative) {
+       if (when >= _limit_pos) {
+               set_out_of_bounds (negative);
+       } else if (negative) {
                snprintf (buf, sizeof (buf), "-%10" PRId64, when);
+               _layout->set_text (buf);
        } else {
                snprintf (buf, sizeof (buf), " %10" PRId64, when);
+               _layout->set_text (buf);
        }
 
-       _layout->set_text (buf);
-
        if (_with_info) {
                framecnt_t rate = _session->frame_rate();
 
@@ -1036,9 +1066,13 @@ AudioClock::set_minsec (framepos_t when, bool /*force*/)
                return;
        }
 
-       print_minsec (when, buf, sizeof (buf), _session->frame_rate());
+       if (when >= _limit_pos || when <= -_limit_pos) {
+               set_out_of_bounds (when < 0);
+       } else {
+               print_minsec (when, buf, sizeof (buf), _session->frame_rate());
+               _layout->set_text (buf);
+       }
 
-       _layout->set_text (buf);
        set_slave_info();
 }
 
@@ -1059,6 +1093,11 @@ AudioClock::set_timecode (framepos_t when, bool /*force*/)
                when = -when;
                negative = true;
        }
+       if (when >= _limit_pos) {
+               set_out_of_bounds (negative);
+               set_slave_info();
+               return;
+       }
 
        if (is_duration) {
                _session->timecode_duration (when, TC);
@@ -1080,7 +1119,7 @@ AudioClock::set_bbt (framepos_t when, framecnt_t offset, bool /*force*/)
        Timecode::BBT_Time BBT;
        bool negative = false;
 
-       if (_off) {
+       if (_off || when >= _limit_pos || when < -_limit_pos) {
                _layout->set_text (" ---|--|----");
                _left_btn.set_text ("", true);
                _right_btn.set_text ("", true);
@@ -1185,25 +1224,30 @@ AudioClock::set_session (Session *s)
 
        if (_session) {
 
+               int64_t limit_sec = UIConfiguration::instance().get_clock_display_limit ();
+               if (limit_sec > 0) {
+                       _limit_pos = (framecnt_t) floor ((double)(limit_sec * _session->frame_rate()));
+               }
+
                Config->ParameterChanged.connect (_session_connections, invalidator (*this), boost::bind (&AudioClock::session_configuration_changed, this, _1), gui_context());
                _session->config.ParameterChanged.connect (_session_connections, invalidator (*this), boost::bind (&AudioClock::session_configuration_changed, this, _1), gui_context());
                _session->tempo_map().PropertyChanged.connect (_session_connections, invalidator (*this), boost::bind (&AudioClock::session_property_changed, this, _1), gui_context());
                _session->tempo_map().MetricPositionChanged.connect (_session_connections, invalidator (*this), boost::bind (&AudioClock::session_property_changed, this, _1), gui_context());
 
-               XMLProperty const * prop;
                XMLNode* node = _session->extra_xml (X_("ClockModes"));
-               AudioClock::Mode amode;
 
                if (node) {
                        for (XMLNodeList::const_iterator i = node->children().begin(); i != node->children().end(); ++i) {
-                               if ((prop = (*i)->property (X_("name"))) && prop->value() == _name) {
+                               std::string name;
+                               if ((*i)->get_property (X_("name"), name) && name == _name) {
 
-                                       if ((prop = (*i)->property (X_("mode"))) != 0) {
-                                               amode = AudioClock::Mode (string_2_enum (prop->value(), amode));
+                                       AudioClock::Mode amode;
+                                       if ((*i)->get_property (X_("mode"), amode)) {
                                                set_mode (amode, true);
                                        }
-                                       if ((prop = (*i)->property (X_("on"))) != 0) {
-                                               set_off (!string_is_affirmative (prop->value()));
+                                       bool on;
+                                       if ((*i)->get_property (X_("on"), on)) {
+                                               set_off (!on);
                                        }
                                        break;
                                }
@@ -1477,6 +1521,11 @@ AudioClock::index_to_field (int index) const
 bool
 AudioClock::on_button_press_event (GdkEventButton *ev)
 {
+       if (!_session || _session->actively_recording()) {
+               /* swallow event, do nothing */
+               return true;
+       }
+
        switch (ev->button) {
        case 1:
                if (editable && !_off) {
@@ -1520,6 +1569,11 @@ AudioClock::on_button_press_event (GdkEventButton *ev)
 bool
 AudioClock::on_button_release_event (GdkEventButton *ev)
 {
+       if (!_session || _session->actively_recording()) {
+               /* swallow event, do nothing */
+               return true;
+       }
+
        if (editable && !_off) {
                if (dragging) {
                        gdk_pointer_ungrab (GDK_CURRENT_TIME);
@@ -1568,7 +1622,7 @@ AudioClock::on_button_release_event (GdkEventButton *ev)
                if (ops_menu == 0) {
                        build_ops_menu ();
                }
-               ops_menu->popup (ev->button, ev->time);
+               ops_menu->popup (1, ev->time);
                return true;
        }
 
@@ -1593,7 +1647,7 @@ AudioClock::on_scroll_event (GdkEventScroll *ev)
        int index;
        int trailing;
 
-       if (editing || _session == 0 || !editable || _off) {
+       if (editing || _session == 0 || !editable || _off || _session->actively_recording())  {
                return false;
        }
 
@@ -1657,7 +1711,7 @@ AudioClock::on_scroll_event (GdkEventScroll *ev)
 bool
 AudioClock::on_motion_notify_event (GdkEventMotion *ev)
 {
-       if (editing || _session == 0 || !dragging) {
+       if (editing || _session == 0 || !dragging || _session->actively_recording()) {
                return false;
        }
 
@@ -1669,8 +1723,7 @@ AudioClock::on_motion_notify_event (GdkEventMotion *ev)
 
 
        if (Keyboard::modifier_state_contains (ev->state,
-                                              Keyboard::PrimaryModifier|Keyboard::SecondaryModifier)) {
-
+                                              Keyboard::PrimaryModifier|Keyboard::SecondaryModifier)) {
                pixel_frame_scale_factor = 0.025f;
        }
 
@@ -1693,9 +1746,9 @@ AudioClock::on_motion_notify_event (GdkEventMotion *ev)
                        set ((framepos_t) floor (pos - drag_accum * frames), false); // minus because up is negative in GTK
                } else {
                        set (0 , false);
-               }
+               }
 
-               drag_accum= 0;
+               drag_accum= 0;
                ValueChanged();  /* EMIT_SIGNAL */
        }
 
@@ -1828,7 +1881,7 @@ AudioClock::timecode_validate_edit (const string&)
        char ignored[2];
 
        if (sscanf (_layout->get_text().c_str(), "%[- _]%" PRId32 ":%" PRId32 ":%" PRId32 "%[:;]%" PRId32,
-                   ignored, &hours, &TC.minutes, &TC.seconds, ignored, &TC.frames) != 6) {
+                   ignored, &hours, &TC.minutes, &TC.seconds, ignored, &TC.frames) != 6) {
                return false;
        }
 
@@ -1943,10 +1996,10 @@ AudioClock::frames_from_bbt_string (framepos_t pos, const string& str) const
        if (is_duration) {
                any.bbt.bars++;
                any.bbt.beats++;
-                return _session->any_duration_to_frames (pos, any);
+               return _session->any_duration_to_frames (pos, any);
        } else {
-                return _session->convert_to_frames (any);
-        }
+               return _session->convert_to_frames (any);
+       }
 }