X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Feditor_rulers.cc;h=68932491e581d48ab124b9960a68b2f338689e6f;hb=5fef65538040fbac1b9edd1847a269aa925a49c9;hp=a8f7cdbf74fe87079924ab0cc8de03621fb997b3;hpb=4b07d015329ebe569457e6f2446bacc62bff2dba;p=ardour.git diff --git a/gtk2_ardour/editor_rulers.cc b/gtk2_ardour/editor_rulers.cc index a8f7cdbf74..68932491e5 100644 --- a/gtk2_ardour/editor_rulers.cc +++ b/gtk2_ardour/editor_rulers.cc @@ -29,25 +29,28 @@ #include -#include "canvas/group.h" +#include "canvas/container.h" #include "canvas/canvas.h" #include "canvas/ruler.h" #include "canvas/debug.h" +#include "canvas/scroll_group.h" #include "ardour/session.h" #include "ardour/tempo.h" #include "ardour/profile.h" #include "gtkmm2ext/gtk_ui.h" +#include "gtkmm2ext/keyboard.h" +#include "ardour_ui.h" #include "editor.h" #include "editing.h" #include "actions.h" #include "gui_thread.h" +#include "ruler_dialog.h" #include "time_axis_view.h" #include "editor_drag.h" #include "editor_cursors.h" -#include "utils.h" #include "i18n.h" @@ -119,32 +122,38 @@ void Editor::initialize_rulers () { ruler_grabbed_widget = 0; - Pango::FontDescription font = get_font_for_style ("editor_time_ruler"); - + /* Not really sure why we can't get this right in a cross-platform way, + but it seems hard. + */ +#ifdef __APPLE__ + Pango::FontDescription font (ARDOUR_UI::config()->get_SmallerFont()); +#else + Pango::FontDescription font (ARDOUR_UI::config()->get_SmallFont()); +#endif _timecode_metric = new TimecodeMetric (this); _bbt_metric = new BBTMetric (this); _minsec_metric = new MinsecMetric (this); _samples_metric = new SamplesMetric (this); - timecode_ruler = new ArdourCanvas::Ruler (_time_markers_group, *_timecode_metric); - timecode_ruler->set_size (ArdourCanvas::Rect (0, 0, ArdourCanvas::COORD_MAX, timebar_height)); + timecode_ruler = new ArdourCanvas::Ruler (_time_markers_group, *_timecode_metric, + ArdourCanvas::Rect (0, 0, ArdourCanvas::COORD_MAX, timebar_height)); timecode_ruler->set_font_description (font); CANVAS_DEBUG_NAME (timecode_ruler, "timecode ruler"); timecode_nmarks = 0; - samples_ruler = new ArdourCanvas::Ruler (_time_markers_group, *_samples_metric); - samples_ruler->set_size (ArdourCanvas::Rect (0, 0, ArdourCanvas::COORD_MAX, timebar_height)); + samples_ruler = new ArdourCanvas::Ruler (_time_markers_group, *_samples_metric, + ArdourCanvas::Rect (0, 0, ArdourCanvas::COORD_MAX, timebar_height)); samples_ruler->set_font_description (font); CANVAS_DEBUG_NAME (samples_ruler, "samples ruler"); - minsec_ruler = new ArdourCanvas::Ruler (_time_markers_group, *_minsec_metric); - minsec_ruler->set_size (ArdourCanvas::Rect (0, 0, ArdourCanvas::COORD_MAX, timebar_height)); + minsec_ruler = new ArdourCanvas::Ruler (_time_markers_group, *_minsec_metric, + ArdourCanvas::Rect (0, 0, ArdourCanvas::COORD_MAX, timebar_height)); minsec_ruler->set_font_description (font); CANVAS_DEBUG_NAME (minsec_ruler, "minsec ruler"); minsec_nmarks = 0; - bbt_ruler = new ArdourCanvas::Ruler (_time_markers_group, *_bbt_metric); - bbt_ruler->set_size (ArdourCanvas::Rect (0, 0, ArdourCanvas::COORD_MAX, timebar_height)); + bbt_ruler = new ArdourCanvas::Ruler (_time_markers_group, *_bbt_metric, + ArdourCanvas::Rect (0, 0, ArdourCanvas::COORD_MAX, timebar_height)); bbt_ruler->set_font_description (font); CANVAS_DEBUG_NAME (bbt_ruler, "bbt ruler"); timecode_nmarks = 0; @@ -164,177 +173,29 @@ Editor::initialize_rulers () lab_children.push_back (Element(mark_label, PACK_SHRINK, PACK_START)); lab_children.push_back (Element(videotl_label, PACK_SHRINK, PACK_START)); - // timecode_ruler->Event.connect (...); - // samples_ruler->Event.connect (...); - // bbt_ruler->Event.connect (...); - // minsec_ruler->Event.connect (...); + /* 1 event handler to bind them all ... */ + + timecode_ruler->Event.connect (sigc::bind (sigc::mem_fun (*this, &Editor::canvas_ruler_event), timecode_ruler, TimecodeRulerItem)); + minsec_ruler->Event.connect (sigc::bind (sigc::mem_fun (*this, &Editor::canvas_ruler_event), minsec_ruler, MinsecRulerItem)); + bbt_ruler->Event.connect (sigc::bind (sigc::mem_fun (*this, &Editor::canvas_ruler_event), bbt_ruler, BBTRulerItem)); + samples_ruler->Event.connect (sigc::bind (sigc::mem_fun (*this, &Editor::canvas_ruler_event), samples_ruler, SamplesRulerItem)); visible_timebars = 0; /*this will be changed below */ } -bool -Editor::ruler_scroll (GdkEventScroll* event) -{ - framepos_t xdelta; - int direction = event->direction; - bool handled = false; - - switch (direction) { - case GDK_SCROLL_UP: - temporal_zoom_step (false); - handled = true; - break; - - case GDK_SCROLL_DOWN: - temporal_zoom_step (true); - handled = true; - break; - - case GDK_SCROLL_LEFT: - xdelta = (current_page_samples() / 2); - if (leftmost_frame > xdelta) { - reset_x_origin (leftmost_frame - xdelta); - } else { - reset_x_origin (0); - } - handled = true; - break; - - case GDK_SCROLL_RIGHT: - xdelta = (current_page_samples() / 2); - if (max_framepos - xdelta > leftmost_frame) { - reset_x_origin (leftmost_frame + xdelta); - } else { - reset_x_origin (max_framepos - current_page_samples()); - } - handled = true; - break; - - default: - /* what? */ - break; - } - - return handled; -} - - -bool -Editor::ruler_button_press (GdkEventButton* /*ev*/) -{ - if (_session == 0) { - return false; - } - -#if 0 - - Widget * grab_widget = 0; - - if (bbt_ruler->is_realized() && ev->window == bbt_ruler->get_window()->gobj()) { - grab_widget = bbt_ruler; - } else if (samples_ruler->is_realized() && ev->window == samples_ruler->get_window()->gobj()) { - grab_widget = samples_ruler; - } else if (minsec_ruler->is_realized() && ev->window == minsec_ruler->get_window()->gobj()) { - grab_widget = minsec_ruler; - } - - if (grab_widget) { - grab_widget->add_modal_grab (); - ruler_grabbed_widget = grab_widget; - } - - if (ev->button == 1) { - // Since we will locate the playhead on button release, cancel any running - // auditions. - if (_session->is_auditioning()) { - _session->cancel_audition (); - } - - /* playhead cursor drag: CursorDrag expects an event with - * canvas coordinates, so convert from window coordinates, - * since for now, rulers are still Gtk::Widgets. - */ - - GdkEventButton canvas_ev = *ev; - ArdourCanvas::Duple d = _track_canvas->window_to_canvas (ArdourCanvas::Duple (ev->x, ev->y)); - canvas_ev.x = rint (d.x); - canvas_ev.y = rint (d.y); - - _drags->set (new CursorDrag (this, *playhead_cursor, false), reinterpret_cast (&canvas_ev)); - _dragging_playhead = true; - } -#endif - - return true; -} - -bool -Editor::ruler_button_release (GdkEventButton* ev) -{ - if (_session == 0) { - return false; - } - - if (_drags->active ()) { - GdkEventButton canvas_ev = *ev; - ArdourCanvas::Duple d = _track_canvas->window_to_canvas (ArdourCanvas::Duple (ev->x, ev->y)); - canvas_ev.x = rint (d.x); - canvas_ev.x = rint (d.y); - _drags->end_grab (reinterpret_cast (&canvas_ev)); - _dragging_playhead = false; - } - - if (ev->button == 3) { - - stop_canvas_autoscroll(); - - framepos_t where = window_event_sample ((GdkEvent*) ev); - - snap_to (where); - popup_ruler_menu (where); - } - - if (ruler_grabbed_widget) { - ruler_grabbed_widget->remove_modal_grab(); - ruler_grabbed_widget = 0; - } - - return true; -} - bool Editor::ruler_label_button_release (GdkEventButton* ev) { - if (ev->button == 3) { - Gtk::Menu* m = dynamic_cast (ActionManager::get_widget (X_("/RulerMenuPopup"))); - if (m) { - m->popup (1, ev->time); + if (Gtkmm2ext::Keyboard::is_context_menu_event (ev)) { + if (!ruler_dialog) { + ruler_dialog = new RulerDialog (); } + ruler_dialog->present (); } return true; } - -bool -Editor::ruler_mouse_motion (GdkEventMotion* ev) -{ - if (_session == 0) { - return false; - } - - if (_drags->active ()) { - GdkEventMotion canvas_ev = *ev; - ArdourCanvas::Duple d = _track_canvas->window_to_canvas (ArdourCanvas::Duple (ev->x, ev->y)); - canvas_ev.x = rint (d.x); - canvas_ev.y = rint (d.y); - _drags->window_motion_handler (reinterpret_cast (&canvas_ev), false); - } - - return true; -} - - void Editor::popup_ruler_menu (framepos_t where, ItemType t) { @@ -376,12 +237,10 @@ Editor::popup_ruler_menu (framepos_t where, ItemType t) case TempoBarItem: ruler_items.push_back (MenuElem (_("New Tempo"), sigc::bind ( sigc::mem_fun(*this, &Editor::mouse_add_new_tempo_event), where))); - ruler_items.push_back (SeparatorElem ()); break; case MeterBarItem: ruler_items.push_back (MenuElem (_("New Meter"), sigc::bind ( sigc::mem_fun(*this, &Editor::mouse_add_new_meter_event), where))); - ruler_items.push_back (SeparatorElem ()); break; case VideoBarItem: @@ -400,70 +259,19 @@ Editor::popup_ruler_menu (framepos_t where, ItemType t) ruler_items.push_back (CheckMenuElem (_("Lock"))); { - Gtk::CheckMenuItem* vtl_lock = static_cast(&ruler_items.back()); - vtl_lock->set_active(is_video_timeline_locked()); - vtl_lock->signal_activate().connect (sigc::mem_fun(*this, &Editor::toggle_video_timeline_locked)); + Gtk::CheckMenuItem* vtl_lock = static_cast(&ruler_items.back()); + vtl_lock->set_active(is_video_timeline_locked()); + vtl_lock->signal_activate().connect (sigc::mem_fun(*this, &Editor::toggle_video_timeline_locked)); } - - ruler_items.push_back (SeparatorElem ()); break; default: break; } - Glib::RefPtr action; - - action = ActionManager::get_action ("Rulers", "toggle-minsec-ruler"); - if (action) { - ruler_items.push_back (MenuElem (*action->create_menu_item())); - } - if (!Profile->get_sae()) { - action = ActionManager::get_action ("Rulers", "toggle-timecode-ruler"); - if (action) { - ruler_items.push_back (MenuElem (*action->create_menu_item())); - } - } - action = ActionManager::get_action ("Rulers", "toggle-samples-ruler"); - if (action) { - ruler_items.push_back (MenuElem (*action->create_menu_item())); - } - action = ActionManager::get_action ("Rulers", "toggle-bbt-ruler"); - if (action) { - ruler_items.push_back (MenuElem (*action->create_menu_item())); - } - action = ActionManager::get_action ("Rulers", "toggle-meter-ruler"); - if (action) { - ruler_items.push_back (MenuElem (*action->create_menu_item())); - } - action = ActionManager::get_action ("Rulers", "toggle-tempo-ruler"); - if (action) { - ruler_items.push_back (MenuElem (*action->create_menu_item())); - } - if (!Profile->get_sae()) { - action = ActionManager::get_action ("Rulers", "toggle-range-ruler"); - if (action) { - ruler_items.push_back (MenuElem (*action->create_menu_item())); - } + if (!ruler_items.empty()) { + editor_ruler_menu->popup (1, gtk_get_current_event_time()); } - action = ActionManager::get_action ("Rulers", "toggle-loop-punch-ruler"); - if (action) { - ruler_items.push_back (MenuElem (*action->create_menu_item())); - } - action = ActionManager::get_action ("Rulers", "toggle-cd-marker-ruler"); - if (action) { - ruler_items.push_back (MenuElem (*action->create_menu_item())); - } - action = ActionManager::get_action ("Rulers", "toggle-marker-ruler"); - if (action) { - ruler_items.push_back (MenuElem (*action->create_menu_item())); - } - action = ActionManager::get_action ("Rulers", "toggle-video-ruler"); - if (action) { - ruler_items.push_back (MenuElem (*action->create_menu_item())); - } - - editor_ruler_menu->popup (1, gtk_get_current_event_time()); no_ruler_shown_update = false; } @@ -906,9 +714,12 @@ Editor::update_tempo_based_rulers (ARDOUR::TempoMap::BBTPointList::const_iterato } } + void Editor::set_timecode_ruler_scale (framepos_t lower, framepos_t upper) { + using namespace std; + framepos_t spacer; framepos_t fr; @@ -916,13 +727,14 @@ Editor::set_timecode_ruler_scale (framepos_t lower, framepos_t upper) return; } - fr = _session->frame_rate(); + fr = _session->frame_rate(); if (lower > (spacer = (framepos_t) (128 * Editor::get_current_zoom ()))) { lower = lower - spacer; } else { lower = 0; } + upper = upper + spacer; framecnt_t const range = upper - lower; @@ -989,20 +801,30 @@ Editor::set_timecode_ruler_scale (framepos_t lower, framepos_t upper) } else if (range <= 8 * 60 * 60 * fr) { /* 4 - 8 hrs*/ timecode_ruler_scale = timecode_show_hours; timecode_mark_modulo = 1; - timecode_nmarks = 2 + 8; + timecode_nmarks = 2 + 8; } else if (range <= 16 * 60 * 60 * fr) { /* 16-24 hrs*/ timecode_ruler_scale = timecode_show_hours; timecode_mark_modulo = 1; timecode_nmarks = 2 + 24; } else { - /* not possible if framepos_t is a 32 bit quantity */ + const framecnt_t hours_in_range = range / (60 * 60 * fr); + const int text_width_rough_guess = 70; /* pixels, very very approximate guess at how wide the tick mark text is */ - timecode_ruler_scale = timecode_show_hours; - timecode_mark_modulo = 4; - timecode_nmarks = 2 + 24; - } + /* Normally we do not need to know anything about the width of the canvas + to set the ruler scale, because the caller has already determined + the width and set lower + upper arguments to this function to match that. + But in this case, where the range defined by lower and uppper can vary + substantially (basically anything from 24hrs+ to several billion years) + trying to decide which tick marks to show does require us to know + about the available width. + */ + + timecode_nmarks = _track_canvas->width() / text_width_rough_guess; + timecode_ruler_scale = timecode_show_many_hours; + timecode_mark_modulo = max ((framecnt_t) 1, 1 + (hours_in_range / timecode_nmarks)); + } } void @@ -1038,7 +860,12 @@ Editor::metric_get_timecode (std::vector& marks, gdou if ((timecode.subframes % timecode_mark_modulo) == 0) { if (timecode.subframes == 0) { mark.style = ArdourCanvas::Ruler::Mark::Major; - snprintf (buf, sizeof(buf), "%s%02u:%02u:%02u:%02u", timecode.negative ? "-" : "", timecode.hours, timecode.minutes, timecode.seconds, timecode.frames); + if (timecode.hours) { + snprintf (buf, sizeof(buf), "%s%u:%02u:%02u", timecode.negative ? "-" : "", timecode.hours, timecode.minutes, timecode.seconds); + } else { + snprintf (buf, sizeof(buf), "%s%u:%02u", timecode.negative ? "-" : "", timecode.minutes, timecode.seconds); + } + } else { mark.style = ArdourCanvas::Ruler::Mark::Minor; snprintf (buf, sizeof(buf), ".%02u", timecode.subframes); @@ -1073,7 +900,11 @@ Editor::metric_get_timecode (std::vector& marks, gdou mark.style = ArdourCanvas::Ruler::Mark::Minor; mark.position = pos; } - snprintf (buf, sizeof(buf), "%s%02u:%02u:%02u:%02u", timecode.negative ? "-" : "", timecode.hours, timecode.minutes, timecode.seconds, timecode.frames); + if (timecode.hours) { + snprintf (buf, sizeof(buf), "%s%u:%02u:%02u", timecode.negative ? "-" : "", timecode.hours, timecode.minutes, timecode.seconds); + } else { + snprintf (buf, sizeof(buf), "%s%u:%02u", timecode.negative ? "-" : "", timecode.minutes, timecode.seconds); + } } else { snprintf (buf, sizeof(buf)," "); mark.style = ArdourCanvas::Ruler::Mark::Micro; @@ -1100,7 +931,11 @@ Editor::metric_get_timecode (std::vector& marks, gdou } else { mark.style = ArdourCanvas::Ruler::Mark::Minor; } - snprintf (buf, sizeof(buf), "%s%02u:%02u:%02u:%02u", timecode.negative ? "-" : "", timecode.hours, timecode.minutes, timecode.seconds, timecode.frames); + if (timecode.hours) { + snprintf (buf, sizeof(buf), "%s%u:%02u:%02u", timecode.negative ? "-" : "", timecode.hours, timecode.minutes, timecode.seconds); + } else { + snprintf (buf, sizeof(buf), "%s%u:%02u", timecode.negative ? "-" : "", timecode.minutes, timecode.seconds); + } } else { snprintf (buf, sizeof(buf)," "); mark.style = ArdourCanvas::Ruler::Mark::Micro; @@ -1123,18 +958,51 @@ Editor::metric_get_timecode (std::vector& marks, gdou _session->timecode_to_sample(timecode, pos, true /* use_offset */, false /* use_subframes */ ); if ((timecode.hours % timecode_mark_modulo) == 0) { mark.style = ArdourCanvas::Ruler::Mark::Major; - snprintf (buf, sizeof(buf), "%s%02u:%02u:%02u:%02u", timecode.negative ? "-" : "", timecode.hours, timecode.minutes, timecode.seconds, timecode.frames); + if (timecode.hours) { + snprintf (buf, sizeof(buf), "%s%u:%02u:%02u", timecode.negative ? "-" : "", timecode.hours, timecode.minutes, timecode.seconds); + } else { + snprintf (buf, sizeof(buf), "%s%u:%02u", timecode.negative ? "-" : "", timecode.minutes, timecode.seconds); + } } else { snprintf (buf, sizeof(buf)," "); mark.style = ArdourCanvas::Ruler::Mark::Micro; - + } mark.label = buf; mark.position = pos; marks.push_back (mark); - Timecode::increment_hours( timecode, _session->config.get_subframes_per_frame() ); + /* Move to next hour */ + Timecode::increment_hours( timecode, _session->config.get_subframes_per_frame() ); + } + break; + + case timecode_show_many_hours: + // Find timecode time of this sample (pos) + _session->sample_to_timecode(pos, timecode, true /* use_offset */, false /* use_subframes */ ); + // Go to next whole hour down + Timecode::hours_floor (timecode); + + for (n = 0; n < timecode_nmarks; ) { + _session->timecode_to_sample(timecode, pos, true /* use_offset */, false /* use_subframes */ ); + if ((timecode.hours % timecode_mark_modulo) == 0) { + mark.style = ArdourCanvas::Ruler::Mark::Major; + if (timecode.hours) { + snprintf (buf, sizeof(buf), "%s%u:%02u:%02u", timecode.negative ? "-" : "", timecode.hours, timecode.minutes, timecode.seconds); + } else { + snprintf (buf, sizeof(buf), "%s%u:%02u", timecode.negative ? "-" : "", timecode.minutes, timecode.seconds); + } + mark.label = buf; + mark.position = pos; + marks.push_back (mark); + ++n; + } + /* can't use Timecode::increment_hours() here because we may be traversing thousands of hours + and doing it 1 hour at a time is just stupid (and slow). + */ + timecode.hours += timecode_mark_modulo; } break; + case timecode_show_frames: // Find timecode time of this sample (pos) _session->sample_to_timecode(pos, timecode, true /* use_offset */, false /* use_subframes */ ); @@ -1150,7 +1018,11 @@ Editor::metric_get_timecode (std::vector& marks, gdou mark.style = ArdourCanvas::Ruler::Mark::Minor; } mark.position = pos; - snprintf (buf, sizeof(buf), "%s%02u:%02u:%02u:%02u", timecode.negative ? "-" : "", timecode.hours, timecode.minutes, timecode.seconds, timecode.frames); + if (timecode.hours) { + snprintf (buf, sizeof(buf), "%s%u:%02u:%02u", timecode.negative ? "-" : "", timecode.hours, timecode.minutes, timecode.seconds); + } else { + snprintf (buf, sizeof(buf), "%s%u:%02u", timecode.negative ? "-" : "", timecode.minutes, timecode.seconds); + } } else { snprintf (buf, sizeof(buf)," "); mark.style = ArdourCanvas::Ruler::Mark::Micro; @@ -1189,7 +1061,7 @@ Editor::compute_bbt_ruler_scale (framepos_t lower, framepos_t upper, bbt_bars = 0; bbt_nmarks = 1; - bbt_ruler_scale = bbt_over; + bbt_ruler_scale = bbt_show_many; switch (_snap_type) { case SnapToBeatDiv2: @@ -1281,7 +1153,7 @@ Editor::compute_bbt_ruler_scale (framepos_t lower, framepos_t upper, } if (bbt_bars > 8192) { - bbt_ruler_scale = bbt_over; + bbt_ruler_scale = bbt_show_many; } else if (bbt_bars > 1024) { bbt_ruler_scale = bbt_show_64; } else if (bbt_bars > 256) { @@ -1670,15 +1542,14 @@ Editor::metric_get_bbt (std::vector& marks, gdouble l break; - case bbt_over: - bbt_nmarks = 1; - snprintf (buf, sizeof(buf), "cannot handle %" PRIu32 " bars", bbt_bars ); - mark.style = ArdourCanvas::Ruler::Mark::Major; - mark.label = buf; - mark.position = lower; - marks.push_back (mark); - - break; + case bbt_show_many: + bbt_nmarks = 1; + snprintf (buf, sizeof(buf), "cannot handle %" PRIu32 " bars", bbt_bars ); + mark.style = ArdourCanvas::Ruler::Mark::Major; + mark.label = buf; + mark.position = lower; + marks.push_back (mark); + break; case bbt_show_64: bbt_nmarks = (gint) (bbt_bars / 64) + 1; @@ -1847,14 +1718,13 @@ sample_to_clock_parts ( framepos_t sample, void Editor::set_minsec_ruler_scale (framepos_t lower, framepos_t upper) { - framepos_t fr; + framepos_t fr = _session->frame_rate() * 1000; framepos_t spacer; if (_session == 0) { return; } - fr = _session->frame_rate() * 1000; /* to prevent 'flashing' */ if (lower > (spacer = (framepos_t)(128 * Editor::get_current_zoom ()))) { @@ -1865,85 +1735,110 @@ Editor::set_minsec_ruler_scale (framepos_t lower, framepos_t upper) upper += spacer; framecnt_t const range = (upper - lower) * 1000; - if (range < (fr / 50)) { - minsec_mark_interval = fr / 1000; /* show 1/1000 seconds */ - minsec_ruler_scale = minsec_show_frames; - minsec_mark_modulo = 10; - } else if (range <= (fr / 10)) { /* 0-0.1 second */ + if (range <= (fr / 10)) { /* 0-0.1 second */ minsec_mark_interval = fr / 1000; /* show 1/1000 seconds */ - minsec_ruler_scale = minsec_show_frames; + minsec_ruler_scale = minsec_show_msecs; minsec_mark_modulo = 10; + minsec_nmarks = 2 + (range / minsec_mark_interval); } else if (range <= (fr / 2)) { /* 0-0.5 second */ minsec_mark_interval = fr / 100; /* show 1/100 seconds */ - minsec_ruler_scale = minsec_show_frames; + minsec_ruler_scale = minsec_show_msecs; minsec_mark_modulo = 100; + minsec_nmarks = 2 + (range / minsec_mark_interval); } else if (range <= fr) { /* 0-1 second */ minsec_mark_interval = fr / 10; /* show 1/10 seconds */ - minsec_ruler_scale = minsec_show_frames; + minsec_ruler_scale = minsec_show_msecs; minsec_mark_modulo = 200; + minsec_nmarks = 2 + (range / minsec_mark_interval); } else if (range <= 2 * fr) { /* 1-2 seconds */ minsec_mark_interval = fr / 10; /* show 1/10 seconds */ - minsec_ruler_scale = minsec_show_frames; + minsec_ruler_scale = minsec_show_msecs; minsec_mark_modulo = 500; + minsec_nmarks = 2 + (range / minsec_mark_interval); } else if (range <= 8 * fr) { /* 2-5 seconds */ minsec_mark_interval = fr / 5; /* show 2 seconds */ - minsec_ruler_scale = minsec_show_frames; + minsec_ruler_scale = minsec_show_msecs; minsec_mark_modulo = 1000; + minsec_nmarks = 2 + (range / minsec_mark_interval); } else if (range <= 16 * fr) { /* 8-16 seconds */ minsec_mark_interval = fr; /* show 1 seconds */ minsec_ruler_scale = minsec_show_seconds; minsec_mark_modulo = 2; + minsec_nmarks = 2 + (range / minsec_mark_interval); } else if (range <= 30 * fr) { /* 10-30 seconds */ minsec_mark_interval = fr; /* show 1 seconds */ minsec_ruler_scale = minsec_show_seconds; minsec_mark_modulo = 5; + minsec_nmarks = 2 + (range / minsec_mark_interval); } else if (range <= 60 * fr) { /* 30-60 seconds */ minsec_mark_interval = fr; /* show 1 seconds */ minsec_ruler_scale = minsec_show_seconds; minsec_mark_modulo = 5; + minsec_nmarks = 2 + (range / minsec_mark_interval); } else if (range <= 2 * 60 * fr) { /* 1-2 minutes */ minsec_mark_interval = 5 * fr; /* show 5 seconds */ minsec_ruler_scale = minsec_show_seconds; minsec_mark_modulo = 3; + minsec_nmarks = 2 + (range / minsec_mark_interval); } else if (range <= 4 * 60 * fr) { /* 4 minutes */ minsec_mark_interval = 5 * fr; /* show 10 seconds */ minsec_ruler_scale = minsec_show_seconds; minsec_mark_modulo = 30; + minsec_nmarks = 2 + (range / minsec_mark_interval); } else if (range <= 10 * 60 * fr) { /* 10 minutes */ minsec_mark_interval = 30 * fr; /* show 30 seconds */ minsec_ruler_scale = minsec_show_seconds; minsec_mark_modulo = 120; + minsec_nmarks = 2 + (range / minsec_mark_interval); } else if (range <= 30 * 60 * fr) { /* 10-30 minutes */ minsec_mark_interval = 60 * fr; /* show 1 minute */ minsec_ruler_scale = minsec_show_minutes; minsec_mark_modulo = 5; + minsec_nmarks = 2 + (range / minsec_mark_interval); } else if (range <= 60 * 60 * fr) { /* 30 minutes - 1hr */ minsec_mark_interval = 2 * 60 * fr; /* show 2 minutes */ minsec_ruler_scale = minsec_show_minutes; minsec_mark_modulo = 10; + minsec_nmarks = 2 + (range / minsec_mark_interval); } else if (range <= 4 * 60 * 60 * fr) { /* 1 - 4 hrs*/ minsec_mark_interval = 5 * 60 * fr; /* show 10 minutes */ minsec_ruler_scale = minsec_show_minutes; minsec_mark_modulo = 30; + minsec_nmarks = 2 + (range / minsec_mark_interval); } else if (range <= 8 * 60 * 60 * fr) { /* 4 - 8 hrs*/ minsec_mark_interval = 20 * 60 * fr; /* show 20 minutes */ minsec_ruler_scale = minsec_show_minutes; minsec_mark_modulo = 60; + minsec_nmarks = 2 + (range / minsec_mark_interval); } else if (range <= 16 * 60 * 60 * fr) { /* 16-24 hrs*/ minsec_mark_interval = 60 * 60 * fr; /* show 60 minutes */ minsec_ruler_scale = minsec_show_hours; minsec_mark_modulo = 2; + minsec_nmarks = 2 + (range / minsec_mark_interval); } else { - /* not possible if framepos_t is a 32 bit quantity */ + const framecnt_t hours_in_range = range / (60 * 60 * fr); + const int text_width_rough_guess = 70; /* pixels, very very approximate guess at how wide the tick mark text is */ + + /* Normally we do not need to know anything about the width of the canvas + to set the ruler scale, because the caller has already determined + the width and set lower + upper arguments to this function to match that. - minsec_mark_interval = 4 * 60 * 60 * fr; /* show 4 hrs */ + But in this case, where the range defined by lower and uppper can vary + substantially (anything from 24hrs+ to several billion years) + trying to decide which tick marks to show does require us to know + about the available width. + */ + + minsec_nmarks = _track_canvas->width() / text_width_rough_guess; + minsec_mark_modulo = max ((framecnt_t) 1, 1 + (hours_in_range / minsec_nmarks)); + minsec_mark_interval = minsec_mark_modulo * (60 * 60 * fr); + minsec_ruler_scale = minsec_show_many_hours; } - minsec_nmarks = 2 + (range / minsec_mark_interval); } void -Editor::metric_get_minsec (std::vector& marks, gdouble lower, gdouble /*upper*/, gint /*maxchars*/) +Editor::metric_get_minsec (std::vector& marks, gdouble lower, gdouble upper, gint /*maxchars*/) { framepos_t pos; framepos_t spacer; @@ -1964,7 +1859,29 @@ Editor::metric_get_minsec (std::vector& marks, gdoubl } pos = (((1000 * (framepos_t) floor(lower)) + (minsec_mark_interval/2))/minsec_mark_interval) * minsec_mark_interval; + switch (minsec_ruler_scale) { + + case minsec_show_msecs: + for (n = 0; n < minsec_nmarks && n < upper; pos += minsec_mark_interval, ++n) { + sample_to_clock_parts (pos, _session->frame_rate(), &hrs, &mins, &secs, &millisecs); + if (millisecs % minsec_mark_modulo == 0) { + if (millisecs == 0) { + mark.style = ArdourCanvas::Ruler::Mark::Major; + } else { + mark.style = ArdourCanvas::Ruler::Mark::Minor; + } + snprintf (buf, sizeof(buf), "%02ld:%02ld:%02ld.%03ld", hrs, mins, secs, millisecs); + } else { + buf[0] = '\0'; + mark.style = ArdourCanvas::Ruler::Mark::Micro; + } + mark.label = buf; + mark.position = pos/1000.0; + marks.push_back (mark); + } + break; + case minsec_show_seconds: for (n = 0; n < minsec_nmarks; pos += minsec_mark_interval, ++n) { sample_to_clock_parts (pos, _session->frame_rate(), &hrs, &mins, &secs, &millisecs); @@ -1974,7 +1891,7 @@ Editor::metric_get_minsec (std::vector& marks, gdoubl } else { mark.style = ArdourCanvas::Ruler::Mark::Minor; } - snprintf (buf, sizeof(buf), "%02ld:%02ld:%02ld.%03ld", hrs, mins, secs, millisecs); + snprintf (buf, sizeof(buf), "%02ld:%02ld:%02ld", hrs, mins, secs); } else { buf[0] = '\0'; mark.style = ArdourCanvas::Ruler::Mark::Micro; @@ -1983,7 +1900,8 @@ Editor::metric_get_minsec (std::vector& marks, gdoubl mark.position = pos/1000.0; marks.push_back (mark); } - break; + break; + case minsec_show_minutes: for (n = 0; n < minsec_nmarks; pos += minsec_mark_interval, ++n) { sample_to_clock_parts (pos, _session->frame_rate(), &hrs, &mins, &secs, &millisecs); @@ -1993,7 +1911,7 @@ Editor::metric_get_minsec (std::vector& marks, gdoubl } else { mark.style = ArdourCanvas::Ruler::Mark::Minor; } - snprintf (buf, sizeof(buf), "%02ld:%02ld:%02ld.%03ld", hrs, mins, secs, millisecs); + snprintf (buf, sizeof(buf), "%02ld:%02ld:%02ld", hrs, mins, secs); } else { buf[0] = '\0'; mark.style = ArdourCanvas::Ruler::Mark::Micro; @@ -2002,13 +1920,14 @@ Editor::metric_get_minsec (std::vector& marks, gdoubl mark.position = pos/1000.0; marks.push_back (mark); } - break; + break; + case minsec_show_hours: for (n = 0; n < minsec_nmarks; pos += minsec_mark_interval, ++n) { sample_to_clock_parts (pos, _session->frame_rate(), &hrs, &mins, &secs, &millisecs); if (hrs % minsec_mark_modulo == 0) { mark.style = ArdourCanvas::Ruler::Mark::Major; - snprintf (buf, sizeof(buf), "%02ld:%02ld:%02ld.%03ld", hrs, mins, secs, millisecs); + snprintf (buf, sizeof(buf), "%02ld:%02ld", hrs, mins); } else { buf[0] = '\0'; mark.style = ArdourCanvas::Ruler::Mark::Micro; @@ -2016,26 +1935,22 @@ Editor::metric_get_minsec (std::vector& marks, gdoubl mark.label = buf; mark.position = pos/1000.0; marks.push_back (mark); + } + break; + + case minsec_show_many_hours: + for (n = 0; n < minsec_nmarks; ) { + sample_to_clock_parts (pos, _session->frame_rate(), &hrs, &mins, &secs, &millisecs); + if (hrs % minsec_mark_modulo == 0) { + mark.style = ArdourCanvas::Ruler::Mark::Major; + snprintf (buf, sizeof(buf), "%02ld:00", hrs); + mark.label = buf; + mark.position = pos/1000.0; + marks.push_back (mark); + ++n; + } + pos += minsec_mark_interval; } - break; - case minsec_show_frames: - for (n = 0; n < minsec_nmarks; pos += minsec_mark_interval, ++n) { - sample_to_clock_parts (pos, _session->frame_rate(), &hrs, &mins, &secs, &millisecs); - if (millisecs % minsec_mark_modulo == 0) { - if (millisecs == 0) { - mark.style = ArdourCanvas::Ruler::Mark::Major; - } else { - mark.style = ArdourCanvas::Ruler::Mark::Minor; - } - snprintf (buf, sizeof(buf), "%02ld:%02ld:%02ld.%03ld", hrs, mins, secs, millisecs); - } else { - buf[0] = '\0'; - mark.style = ArdourCanvas::Ruler::Mark::Micro; - } - mark.label = buf; - mark.position = pos/1000.0; - marks.push_back (mark); - } - break; - } + break; + } }