diff --git a/gtk2_ardour/audio_trigger_properties_box.cc b/gtk2_ardour/audio_trigger_properties_box.cc index 1ee305e390..83fdd4687b 100644 --- a/gtk2_ardour/audio_trigger_properties_box.cc +++ b/gtk2_ardour/audio_trigger_properties_box.cc @@ -74,34 +74,34 @@ AudioTriggerPropertiesBox::AudioTriggerPropertiesBox () bpm_table->attach (_stretch_toggle, 0, 1, row, row + 1, Gtk::FILL, Gtk::SHRINK); bpm_table->attach (_stretch_selector, 1, 4, row, row + 1, Gtk::FILL, Gtk::SHRINK); row++; - label = manage (new Gtk::Label (_("BPM:"))); - label->set_alignment (1.0, 0.5); - bpm_table->attach (*label, 0, 1, row, row + 1, Gtk::FILL, Gtk::SHRINK); + _bpm_label.set_text(_("BPM:")); + _bpm_label.set_alignment (1.0, 0.5); + bpm_table->attach (_bpm_label, 0, 1, row, row + 1, Gtk::FILL, Gtk::SHRINK); bpm_table->attach (_abpm_label, 1, 2, row, row + 1, Gtk::FILL, Gtk::SHRINK); - ArdourButton *half = manage (new ArdourButton (_("/2"))); - half->signal_clicked.connect(sigc::bind (sigc::mem_fun(*this, &AudioTriggerPropertiesBox::MultiplyTempo), 0.5)); - bpm_table->attach (*half, 2, 3, row, row + 1, Gtk::SHRINK, Gtk::SHRINK); - ArdourButton *dbl = manage (new ArdourButton (_("x2"))); - dbl->signal_clicked.connect(sigc::bind (sigc::mem_fun(*this, &AudioTriggerPropertiesBox::MultiplyTempo), 2.0)); - bpm_table->attach (*dbl, 3, 4, row, row + 1, Gtk::SHRINK, Gtk::SHRINK); + _half_button.set_text(_("/2")); + _half_button.signal_clicked.connect(sigc::bind (sigc::mem_fun(*this, &AudioTriggerPropertiesBox::MultiplyTempo), 0.5)); + bpm_table->attach (_half_button, 2, 3, row, row + 1, Gtk::FILL, Gtk::SHRINK); + _dbl_button.set_text(_("x2")); + _dbl_button.signal_clicked.connect(sigc::bind (sigc::mem_fun(*this, &AudioTriggerPropertiesBox::MultiplyTempo), 2.0)); + bpm_table->attach (_dbl_button, 3, 4, row, row + 1, Gtk::FILL, Gtk::SHRINK); row++; - label = manage (new Gtk::Label (_("Meter:"))); - label->set_alignment (1.0, 0.5); - bpm_table->attach (*label, 0, 1, row, row + 1, Gtk::FILL, Gtk::SHRINK); + _meter_label.set_text(_("Meter:")); + _meter_label.set_alignment (1.0, 0.5); + bpm_table->attach (_meter_label, 0, 1, row, row + 1, Gtk::FILL, Gtk::SHRINK); bpm_table->attach (_meter_selector, 1, 4, row, row + 1, Gtk::FILL, Gtk::SHRINK); row++; - label = manage (new Gtk::Label (_("Clip Length:"))); - label->set_alignment (1.0, 0.5); - Gtk::Label *bar_label = manage (new Gtk::Label (_("(bars)"))); - bar_label->set_alignment (0.0, 0.5); - bpm_table->attach (*label, 0, 1, row, row + 1, Gtk::FILL, Gtk::SHRINK); + _length_label.set_text(_("Clip Length:")); + _length_label.set_alignment (1.0, 0.5); + _bar_label.set_text(_("(bars)")); + _bar_label.set_alignment (0.0, 0.5); + bpm_table->attach (_length_label,0, 1, row, row + 1, Gtk::FILL, Gtk::SHRINK); bpm_table->attach (_bar_spinner, 1, 2, row, row + 1, Gtk::FILL, Gtk::SHRINK); - bpm_table->attach (*bar_label, 2, 4, row, row + 1, Gtk::FILL, Gtk::SHRINK); + bpm_table->attach (_bar_label, 2, 4, row, row + 1, Gtk::FILL, Gtk::SHRINK); ArdourWidgets::Frame* eTempoBox = manage (new ArdourWidgets::Frame); eTempoBox->set_label("Stretch Options"); @@ -237,9 +237,34 @@ AudioTriggerPropertiesBox::on_trigger_changed (const PBD::PropertyChange& pc) if (pc.contains (Properties::stretch_mode) || pc.contains (Properties::stretchable)) { _stretch_toggle.set_active (at->stretchable () ? Gtkmm2ext::ExplicitActive : Gtkmm2ext::Off); - - _stretch_selector.set_sensitive(at->stretchable ()); _stretch_selector.set_text(stretch_mode_to_string(at->stretch_mode ())); + + /* set widget sensitivity based on stretchable button state */ + bool follow_widgets_sensitive = at->stretchable (); + + if (follow_widgets_sensitive) { + _stretch_selector.set_sensitive(true); + _meter_selector.set_sensitive(true); + _bar_spinner.set_sensitive(true); + _bar_label.set_sensitive(true); + _length_label.set_sensitive(true); + _meter_label.set_sensitive(true); + _bpm_label.set_sensitive(true); + _half_button.set_sensitive(true); + _dbl_button.set_sensitive(true); + _abpm_label.set_sensitive(true); + } else { + _stretch_selector.set_sensitive(false); + _meter_selector.set_sensitive(false); + _bar_spinner.set_sensitive(false); + _bar_label.set_sensitive(false); + _length_label.set_sensitive(false); + _meter_label.set_sensitive(false); + _bpm_label.set_sensitive(false); + _half_button.set_sensitive(false); + _dbl_button.set_sensitive(false); + _abpm_label.set_sensitive(false); + } } _ignore_changes = false; diff --git a/gtk2_ardour/audio_trigger_properties_box.h b/gtk2_ardour/audio_trigger_properties_box.h index 859760daa3..332b811d7c 100644 --- a/gtk2_ardour/audio_trigger_properties_box.h +++ b/gtk2_ardour/audio_trigger_properties_box.h @@ -76,6 +76,11 @@ private: AudioClock _length_clock; AudioClock _start_clock; + Gtk::Label _bpm_label; + Gtk::Label _length_label; + Gtk::Label _bar_label; + Gtk::Label _meter_label; + ArdourWidgets::ArdourDropdown _meter_selector; Gtk::Adjustment _bar_adjustment; @@ -87,6 +92,9 @@ private: ArdourWidgets::ArdourButton _abpm_label; + ArdourWidgets::ArdourButton _half_button; + ArdourWidgets::ArdourButton _dbl_button; + bool _ignore_changes; }; diff --git a/gtk2_ardour/cuebox_ui.cc b/gtk2_ardour/cuebox_ui.cc index 247efbb623..696aeaaea0 100644 --- a/gtk2_ardour/cuebox_ui.cc +++ b/gtk2_ardour/cuebox_ui.cc @@ -23,6 +23,7 @@ #include "ardour/session.h" #include "ardour/triggerbox.h" +#include "canvas/circle.h" #include "canvas/polygon.h" #include "canvas/text.h" @@ -63,17 +64,7 @@ CueEntry::CueEntry (Item* item, uint64_t cue_index) set_outline (false); set_fill_color (UIConfiguration::instance ().color ("theme:bg")); - play_button = new ArdourCanvas::Rectangle (this); - play_button->set_outline (false); - play_button->set_fill (true); - play_button->name = string_compose ("playbutton %1", _cue_idx); - play_button->show (); - - play_shape = new ArdourCanvas::Polygon (play_button); - play_shape->name = string_compose ("playshape %1", _cue_idx); - play_shape->show (); - - name_button = new ArdourCanvas::Rectangle (this); + name_button = new ArdourCanvas::Circle (this); name_button->set_outline (false); name_button->set_fill (true); name_button->name = ("slot_selector_button"); @@ -81,7 +72,6 @@ CueEntry::CueEntry (Item* item, uint64_t cue_index) name_text = new Text (name_button); name_text->set (string_compose ("%1", (char)('A' + _cue_idx))); // XXX not translatable - name_text->set_ignore_events (false); name_text->show (); @@ -102,10 +92,7 @@ CueEntry::event_handler (GdkEvent* ev) break; case GDK_ENTER_NOTIFY: if (ev->crossing.detail != GDK_NOTIFY_INFERIOR) { - name_text->set_color (UIConfiguration::instance ().color ("neutral:foregroundest")); - play_shape->set_outline_color (UIConfiguration::instance ().color ("neutral:foregroundest")); - play_button->set_fill_color (HSV (fill_color ()).lighter (0.15).color ()); - name_button->set_fill_color (HSV (fill_color ()).lighter (0.15).color ()); +// name_button->set_fill_color (UIConfiguration::instance ().color ("neutral:foregroundest")); set_fill_color (HSV (fill_color ()).lighter (0.15).color ()); } break; @@ -129,23 +116,17 @@ CueEntry::_size_allocate (ArdourCanvas::Rect const& alloc) const Distance width = _rect.width (); const Distance height = _rect.height (); - play_button->set (ArdourCanvas::Rect (0, 0, height, height)); - name_button->set (ArdourCanvas::Rect (height, 0, width, height)); - const double scale = UIConfiguration::instance ().get_ui_scale (); - _poly_margin = 2. * scale; - _poly_size = height - 2 * _poly_margin; - shape_play_button (); - float tleft = height; // make room for the play button - float twidth = name_button->width () - _poly_margin * 2; + name_button->set_center ( Duple(height/2, height/2) ); + name_button->set_radius ( (height/2)- 2*scale ); - name_text->size_allocate (ArdourCanvas::Rect (0, 0, width, height)); - name_text->set_position (Duple (tleft + _poly_margin, _poly_margin - 0.5)); + name_text->size_allocate (ArdourCanvas::Rect (0, 0, height, height)); + name_text->set_position (Duple (4. * scale, 2.5 * scale)); name_text->clamp_width (width - height); /* font scale may have changed. uiconfig 'embeds' the ui-scale in the font */ - name_text->set_font_description (UIConfiguration::instance ().get_NormalFont ()); + name_text->set_font_description (UIConfiguration::instance ().get_SmallBoldMonospaceFont ()); } void @@ -164,7 +145,7 @@ CueEntry::render (ArdourCanvas::Rect const& area, Cairo::RefPtr } float width = _rect.width (); - float height = _rect.height (); + float height = _rect.height (); const double scale = UIConfiguration::instance ().get_ui_scale (); @@ -176,7 +157,26 @@ CueEntry::render (ArdourCanvas::Rect const& area, Cairo::RefPtr render_children (area, context); - if (_cue_idx == 0) { + { //Play triangle, needs to match TriggerEntry buttons exactly + context->set_line_width (1 * scale); + + float margin = 4 * scale; + float size = height - 2 * margin; + + context->set_identity_matrix (); + context->translate (self.x0, self.y0 - 0.5); + context->move_to (height + margin, margin); + context->rel_line_to (0, size); + context->rel_line_to (size, -size / 2); + context->close_path (); + set_source_rgba (context, UIConfiguration::instance ().color ("neutral:midground")); + context->stroke (); + context->set_identity_matrix (); + + context->set_line_width (1); + } + + if (false /*_cue_idx == 0*/) { Cairo::RefPtr drop_shadow_pattern = Cairo::LinearGradient::create (0.0, 0.0, 0.0, 6 * scale); drop_shadow_pattern->add_color_stop_rgba (0, 0, 0, 0, 0.7); drop_shadow_pattern->add_color_stop_rgba (1, 0, 0, 0, 0.0); @@ -186,47 +186,19 @@ CueEntry::render (ArdourCanvas::Rect const& area, Cairo::RefPtr } } -void -CueEntry::shape_play_button () -{ - Points p; - - p.push_back (Duple (_poly_margin, _poly_margin)); - p.push_back (Duple (_poly_margin, _poly_size)); - p.push_back (Duple (_poly_size, 0.5 + _poly_size / 2.)); - - play_shape->set (p); - - if (false /*TODO*/) { - play_shape->set_outline (false); - play_shape->set_fill (true); - } else { - play_shape->set_outline (true); - play_shape->set_fill (false); - } -} - void CueEntry::set_default_colors () { - set_fill_color (UIConfiguration::instance ().color ("theme:bg")); - play_button->set_fill_color (UIConfiguration::instance ().color ("theme:bg")); - play_button->set_outline_color (UIConfiguration::instance ().color ("theme:bg")); - name_button->set_fill_color (UIConfiguration::instance ().color ("theme:bg")); - name_text->set_fill_color (UIConfiguration::instance ().color ("theme:bg")); + color_t bg_col = UIConfiguration::instance ().color ("theme:bg"); + //alternating darker bands if ((_cue_idx / 2) % 2 == 0) { - set_fill_color (HSV (fill_color ()).darker (0.15).color ()); - play_button->set_fill_color (HSV (fill_color ()).darker (0.15).color ()); - play_button->set_outline_color (HSV (fill_color ()).darker (0.15).color ()); - name_button->set_fill_color (HSV (fill_color ()).darker (0.15).color ()); - name_text->set_fill_color (HSV (fill_color ()).darker (0.15).color ()); + bg_col = HSV (bg_col).darker (0.25).color (); } - name_text->set_color (UIConfiguration::instance ().color ("neutral:foreground")); - - play_shape->set_outline_color (UIConfiguration::instance ().color ("neutral:foreground")); - play_shape->set_fill_color (UIConfiguration::instance ().color ("neutral:foreground")); + set_fill_color (bg_col); + name_button->set_fill_color (UIConfiguration::instance ().color ("neutral:midground")); + name_text->set_color (UIConfiguration::instance ().color ("neutral:background")); } void @@ -317,9 +289,6 @@ CueBoxUI::context_menu (uint64_t idx) b = BBT_Offset (-1, 0, 0); qitems.push_back (MenuElem (TriggerUI::quantize_length_to_string (b), sigc::bind (sigc::mem_fun (*this, &CueBoxUI::set_all_quantization), b, idx))); - Menu* load_menu = manage (new Menu); - MenuList& loitems (load_menu->items ()); - items.push_back (MenuElem (_("Set All Follow Actions..."), *follow_menu)); items.push_back (MenuElem (_("Set All Launch Styles..."), *launch_menu)); items.push_back (MenuElem (_("Set All Quantizations..."), *quant_menu)); @@ -463,7 +432,6 @@ CueBoxUI::build () _slots.push_back (te); #if 0 - te->play_button->Event.connect (sigc::bind (sigc::mem_fun (*this, &CueBoxUI::trigger_scene), n)); te->name_text->Event.connect (sigc::bind (sigc::mem_fun (*this, &CueBoxUI::text_event), n)); #endif te->Event.connect (sigc::bind (sigc::mem_fun (*this, &CueBoxUI::event), n)); diff --git a/gtk2_ardour/cuebox_ui.h b/gtk2_ardour/cuebox_ui.h index 97e458ecfe..d68c28bf4a 100644 --- a/gtk2_ardour/cuebox_ui.h +++ b/gtk2_ardour/cuebox_ui.h @@ -38,6 +38,7 @@ namespace ArdourCanvas { class Text; class Polygon; + class Circle; } class CueEntry : public ArdourCanvas::Rectangle @@ -46,10 +47,7 @@ public: CueEntry (ArdourCanvas::Item* item, uint64_t cue_index); ~CueEntry (); - ArdourCanvas::Rectangle* play_button; - ArdourCanvas::Polygon* play_shape; - - ArdourCanvas::Rectangle* name_button; + ArdourCanvas::Circle* name_button; ArdourCanvas::Text* name_text; void render (ArdourCanvas::Rect const& area, Cairo::RefPtr context) const; diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index d7cec55753..4c0606e26c 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -1723,6 +1723,11 @@ private: PBD::Signal0 EditorFreeze; PBD::Signal0 EditorThaw; + void begin_tempo_map_edit (); + void abort_tempo_map_edit (); + void commit_tempo_map_edit (); + void mid_tempo_change (); + private: friend class DragManager; friend class EditorRouteGroups; @@ -1777,8 +1782,8 @@ private: void remove_tempo_marker (ArdourCanvas::Item*); void remove_meter_marker (ArdourCanvas::Item*); - gint real_remove_tempo_marker (Temporal::TempoPoint*); - gint real_remove_meter_marker (Temporal::MeterPoint*); + gint real_remove_tempo_marker (Temporal::TempoPoint const *); + gint real_remove_meter_marker (Temporal::MeterPoint const *); void edit_tempo_marker (TempoMarker&); void edit_meter_marker (MeterMarker&); @@ -1834,22 +1839,26 @@ private: Gtk::Menu* new_transport_marker_menu; ArdourCanvas::Item* marker_menu_item; - typedef std::list Marks; - Marks metric_marks; - - typedef std::list Curves; - Curves tempo_curves; + typedef std::list Marks; + Marks tempo_marks; + Marks meter_marks; + Marks bbt_marks; void remove_metric_marks (); void draw_metric_marks (Temporal::TempoMap::Metrics const & metrics); + void draw_tempo_marks (); + void draw_meter_marks (); + void draw_bbt_marks (); void compute_current_bbt_points (Temporal::TempoMapPoints& grid, samplepos_t left, samplepos_t right); void reassociate_metric_markers (Temporal::TempoMap::SharedPtr const &); - void reassociate_metric_marker (Temporal::TempoMap::SharedPtr const & tmap, Temporal::TempoMap::Metrics & metric, ArdourMarker& marker); - void begin_tempo_map_edit (); - void abort_tempo_map_edit (); - void commit_tempo_map_edit (); + void reassociate_metric_marker (Temporal::TempoMap::SharedPtr const & tmap, Temporal::TempoMap::Metrics & metric, MetricMarker& marker); + void make_bbt_marker (Temporal::MusicTimePoint const *); + void make_meter_marker (Temporal::MeterPoint const *); + void make_tempo_marker (Temporal::TempoPoint const * ts, double& min_tempo, double& max_tempo, Temporal::TempoPoint const *& prev_ts, uint32_t tc_color, samplecnt_t sr); + void update_tempo_curves (double min_tempo, double max_tempo, samplecnt_t sr); + void tempo_map_changed (); void redisplay_grid (bool immediate_redraw); diff --git a/gtk2_ardour/editor_drag.cc b/gtk2_ardour/editor_drag.cc index 0a5f4b1a9d..c67798fa1f 100644 --- a/gtk2_ardour/editor_drag.cc +++ b/gtk2_ardour/editor_drag.cc @@ -3600,73 +3600,15 @@ TempoMarkerDrag::motion (GdkEvent* event, bool first_move) TempoMap::SharedPtr map (TempoMap::use()); if (first_move) { - - // mvc drag - create a dummy marker to catch events, hide it. - - char name[64]; - snprintf (name, sizeof (name), "%.2f", _marker->tempo().note_types_per_minute()); - - _marker = new TempoMarker ( - *_editor, - *_editor->tempo_group, - UIConfiguration::instance().color ("tempo marker"), - name, - _marker->tempo() - ); - - /* use the new marker for the grab */ - swap_grab (&_marker->the_item(), 0, GDK_CURRENT_TIME); - _marker->hide(); - /* get current state */ _before_state = &map->get_state(); - - if (!_copy) { - - _editor->begin_reversible_command (_("move tempo mark")); - - } else { - - timepos_t const pointer = adjusted_current_time (event, false); - BBT_Time pointer_bbt = map->bbt_at (pointer); - Temporal::TempoMetric metric = map->metric_at (pointer); - Temporal::MeterPoint const & meter = metric.meter(); - Temporal::TempoPoint const & tempo = metric.tempo(); - BBT_Time bbt = tempo.bbt(); - - /* we can't add a tempo where one currently exists */ - if (bbt < pointer_bbt) { - bbt = meter.bbt_add (bbt, BBT_Offset (0, 1, 0)); - } else { - bbt = meter.bbt_add (bbt, BBT_Offset (0, -1, 0)); - } - - _editor->begin_reversible_command (_("copy tempo mark")); - - timepos_t pos; - - if (map->time_domain() == AudioTime) { - pos = timepos_t (map->sample_at (bbt)); - } else { - pos = timepos_t (map->quarters_at (bbt)); - } - - _marker->reset_tempo (map->set_tempo (tempo, pos)); - -#warning paul, need a return status from set_tempo -#if 0 - if (!) { - aborted (true); - return; - } -#endif - } + _editor->begin_reversible_command (_("move tempo mark")); } if (ArdourKeyboard::indicates_constraint (event->button.state) && ArdourKeyboard::indicates_copy (event->button.state)) { double new_bpm = max (1.5, _grab_bpm.end_note_types_per_minute() + ((grab_y() - min (-1.0, current_pointer_y())) / 5.0)); stringstream strs; - map->change_tempo (_marker->tempo(), Tempo (_marker->tempo().note_types_per_minute(), _marker->tempo().note_type(), new_bpm)); + map->change_tempo (const_cast(_marker->tempo()), Tempo (_marker->tempo().note_types_per_minute(), _marker->tempo().note_type(), new_bpm)); strs << "end:" << fixed << setprecision(3) << new_bpm; show_verbose_cursor_text (strs.str()); @@ -3674,31 +3616,19 @@ TempoMarkerDrag::motion (GdkEvent* event, bool first_move) /* use vertical movement to alter tempo .. should be log */ double new_bpm = max (1.5, _grab_bpm.note_types_per_minute() + ((grab_y() - min (-1.0, current_pointer_y())) / 5.0)); stringstream strs; - map->change_tempo (_marker->tempo(), Tempo (new_bpm, _marker->tempo().note_type(), _marker->tempo().end_note_types_per_minute())); + map->change_tempo (const_cast(_marker->tempo()), Tempo (new_bpm, _marker->tempo().note_type(), _marker->tempo().end_note_types_per_minute())); strs << "start:" << fixed << setprecision(3) << new_bpm; show_verbose_cursor_text (strs.str()); } else if (_movable) { - timepos_t pos = adjusted_current_time (event); - - std::cerr << " going to move " << &_marker->tempo() << std::endl; map->move_tempo (_marker->tempo(), pos, false); - - show_verbose_cursor_time (_marker->tempo().time()); - } - - - if (_movable && (!first_move || !_copy)) { - - timepos_t pos = adjusted_current_time (event); - - map->move_tempo (_marker->tempo(), pos, false); - show_verbose_cursor_time (_marker->tempo().time()); + _editor->mid_tempo_change (); } } + void TempoMarkerDrag::finished (GdkEvent* event, bool movement_occurred) { @@ -3727,10 +3657,6 @@ TempoMarkerDrag::finished (GdkEvent* event, bool movement_occurred) _editor->session()->add_command (new MementoCommand (new Temporal::TempoMap::MementoBinder(), _before_state, &after)); _editor->commit_reversible_command (); - - // delete the dummy marker we used for visual representation while moving. - // a new visual marker will show up automatically. - delete _marker; } void diff --git a/gtk2_ardour/editor_drag.h b/gtk2_ardour/editor_drag.h index 0c51ef9d4a..bce6d88b57 100644 --- a/gtk2_ardour/editor_drag.h +++ b/gtk2_ardour/editor_drag.h @@ -875,7 +875,7 @@ public: private: TempoMarker* _marker; - Temporal::TempoPoint* _real_section; + Temporal::TempoPoint const * _real_section; bool _copy; bool _movable; @@ -968,7 +968,7 @@ public: private: Temporal::Beats _grab_qn; - Temporal::TempoPoint* _tempo; + Temporal::TempoPoint const * _tempo; XMLNode* _before_state; bool _drag_valid; }; diff --git a/gtk2_ardour/editor_markers.cc b/gtk2_ardour/editor_markers.cc index 8bb5ef51b3..25ef61eee0 100644 --- a/gtk2_ardour/editor_markers.cc +++ b/gtk2_ardour/editor_markers.cc @@ -1531,9 +1531,9 @@ Editor::marker_menu_edit () dynamic_cast_marker_object (marker_menu_item->get_data ("marker"), &mm, &tm); if (mm) { - edit_meter_section (mm->meter()); + edit_meter_section (const_cast(mm->meter())); } else if (tm) { - edit_tempo_section (tm->tempo()); + edit_tempo_section (const_cast(tm->tempo())); } } @@ -1567,11 +1567,11 @@ Editor::toggle_tempo_type () TempoMap::SharedPtr tmap (TempoMap::write_copy()); reassociate_metric_markers (tmap); - Temporal::TempoPoint & tempo = tm->tempo(); + Temporal::TempoPoint const & tempo = tm->tempo(); XMLNode &before = tmap->get_state(); - tmap->set_ramped (tempo, !tempo.ramped()); + tmap->set_ramped (const_cast(tempo), !tempo.ramped()); XMLNode &after = tmap->get_state(); _session->add_command (new MementoCommand (new Temporal::TempoMap::MementoBinder(), &before, &after)); @@ -1595,9 +1595,9 @@ Editor::toggle_tempo_clamped () XMLNode &before = tmap->get_state(); reassociate_metric_markers (tmap); - Temporal::Tempo & tempo (tm->tempo()); + Temporal::Tempo const & tempo (tm->tempo()); - tempo.set_clamped (!tempo.clamped()); + const_cast(tempo).set_clamped (!tempo.clamped()); XMLNode &after = tmap->get_state(); _session->add_command (new MementoCommand (new Temporal::TempoMap::MementoBinder(), &before, &after)); @@ -1622,9 +1622,9 @@ Editor::ramp_to_next_tempo () XMLNode &before = tmap->get_state(); reassociate_metric_markers (tmap); - Temporal::TempoPoint & tempo (tm->tempo()); + Temporal::TempoPoint const & tempo (tm->tempo()); - tmap->set_ramped (tempo, !tempo.ramped()); + tmap->set_ramped (const_cast(tempo), !tempo.ramped()); XMLNode &after = tmap->get_state(); _session->add_command (new MementoCommand (new Temporal::TempoMap::MementoBinder(), &before, &after)); diff --git a/gtk2_ardour/editor_tempodisplay.cc b/gtk2_ardour/editor_tempodisplay.cc index 5e4f4a6d9b..4329f0e030 100644 --- a/gtk2_ardour/editor_tempodisplay.cc +++ b/gtk2_ardour/editor_tempodisplay.cc @@ -73,36 +73,40 @@ Editor::remove_metric_marks () { /* don't delete these while handling events, just punt till the GUI is idle */ - for (Marks::iterator x = metric_marks.begin(); x != metric_marks.end(); ++x) { - delete_when_idle (*x); + for (auto & m : tempo_marks) { + delete_when_idle (m); + } + for (auto & m : meter_marks) { + delete_when_idle (m); + } + for (auto & m : bbt_marks) { + delete_when_idle (m); } - metric_marks.clear (); - for (Curves::iterator x = tempo_curves.begin(); x != tempo_curves.end(); ++x) { - delete (*x); - } - tempo_curves.clear (); + tempo_marks.clear (); + meter_marks.clear (); + bbt_marks.clear (); } -struct CurveComparator { - bool operator() (TempoCurve const * a, TempoCurve const * b) { - return a->tempo().sclock() < b->tempo().sclock(); - } -}; - void Editor::reassociate_metric_markers (TempoMap::SharedPtr const & tmap) { TempoMap::Metrics metrics; tmap->get_metrics (metrics); - for (auto & marker : metric_marks) { - reassociate_metric_marker (tmap, metrics, *marker); + for (auto & m : tempo_marks) { + reassociate_metric_marker (tmap, metrics, *m); + } + for (auto & m : meter_marks) { + reassociate_metric_marker (tmap, metrics, *m); + } + for (auto & m : bbt_marks) { + reassociate_metric_marker (tmap, metrics, *m); } } void -Editor::reassociate_metric_marker (TempoMap::SharedPtr const & tmap, TempoMap::Metrics & metrics, ArdourMarker& marker) +Editor::reassociate_metric_marker (TempoMap::SharedPtr const & tmap, TempoMap::Metrics & metrics, MetricMarker& marker) { TempoMarker* tm; MeterMarker* mm; @@ -157,70 +161,266 @@ Editor::reassociate_metric_marker (TempoMap::SharedPtr const & tmap, TempoMap::M } void -Editor::draw_metric_marks (TempoMap::Metrics const & metrics) +Editor::make_bbt_marker (MusicTimePoint const * mtp) +{ + if (mtp->map().time_domain() == BeatTime) { + bbt_marks.push_back (new BBTMarker (*this, *bbt_ruler, UIConfiguration::instance().color ("meter marker music"), "bar!", *mtp)); + } else { + bbt_marks.push_back (new BBTMarker (*this, *bbt_ruler, UIConfiguration::instance().color ("meter marker"), "foo!", *mtp)); + } +} + +void +Editor::make_meter_marker (Temporal::MeterPoint const * ms) +{ + char buf[64]; + + snprintf (buf, sizeof(buf), "%d/%d", ms->divisions_per_bar(), ms->note_value ()); + if (ms->map().time_domain() == BeatTime) { + meter_marks.push_back (new MeterMarker (*this, *meter_group, UIConfiguration::instance().color ("meter marker music"), buf, *ms)); + } else { + meter_marks.push_back (new MeterMarker (*this, *meter_group, UIConfiguration::instance().color ("meter marker"), buf, *ms)); + } +} + +void +Editor::make_tempo_marker (Temporal::TempoPoint const * ts, double& min_tempo, double& max_tempo, TempoPoint const *& prev_ts, uint32_t tc_color, samplecnt_t sr) +{ + max_tempo = max (max_tempo, ts->note_types_per_minute()); + max_tempo = max (max_tempo, ts->end_note_types_per_minute()); + min_tempo = min (min_tempo, ts->note_types_per_minute()); + min_tempo = min (min_tempo, ts->end_note_types_per_minute()); + + const std::string tname (X_("")); + char const * color_name; + + /* XXX not sure this is the right thing to do here (differentiate time + * domains with color). + */ + + if (ts->map().time_domain() == BeatTime) { + color_name = X_("tempo marker music"); + } else { + color_name = X_("tempo marker music"); + } + + tempo_marks.push_back (new TempoMarker (*this, *tempo_group, UIConfiguration::instance().color (color_name), tname, *ts, ts->sample (sr), tc_color)); + + /* XXX the point of this code was "a jump in tempo by more than 1 ntpm results in a red + tempo mark pointer." (3a7bc1fd3f32f0) + */ + + if (prev_ts && abs (prev_ts->end_note_types_per_minute() - ts->note_types_per_minute()) < 1.0) { + tempo_marks.back()->set_points_color (UIConfiguration::instance().color ("tempo marker music")); + } else { + tempo_marks.back()->set_points_color (UIConfiguration::instance().color ("tempo marker")); + } + + prev_ts = ts; +} + +void +Editor::draw_metric_marks (Temporal::TempoMap::Metrics const &) +{ + draw_tempo_marks (); + draw_meter_marks (); + draw_bbt_marks (); +} + +void +Editor::draw_tempo_marks () { if (!_session) { return; } - char buf[64]; - TempoPoint* prev_ts = 0; + const uint32_t tc_color = UIConfiguration::instance().color ("tempo curve"); + const samplecnt_t sr (_session->sample_rate()); + TempoPoint const * prev_ts = 0; + Temporal::TempoMap::SharedPtr tmap (TempoMap::use()); + TempoMap::Tempos const & tempi (tmap->tempos()); + TempoMap::Tempos::const_iterator t = tempi.begin(); + Marks::iterator mm = tempo_marks.begin(); double max_tempo = 0.0; double min_tempo = DBL_MAX; - const samplecnt_t sr (_session->sample_rate()); - remove_metric_marks (); // also clears tempo curves + std::cerr << "**** BEGIN DRAW TEMPO\n"; - for (TempoMap::Metrics::const_iterator i = metrics.begin(); i != metrics.end(); ++i) { - Temporal::MeterPoint *ms; - Temporal::TempoPoint *ts; - Temporal::MusicTimePoint *mtp; + while (t != tempi.end() && mm != tempo_marks.end()) { - /* must check MusicTimePoint first, since it IS-A TempoPoint - * and MeterPoint. - */ + Temporal::Point const & mark_point ((*mm)->point()); + Temporal::TempoPoint const & metric_point (*t); - if ((mtp = dynamic_cast(*i)) != 0) { + std::cerr << "\tmark @ " << mark_point.sclock() << " tempo @ " << metric_point.sclock() << std::endl; - if (mtp->map().time_domain() == BeatTime) { - metric_marks.push_back (new BBTMarker (*this, *bbt_ruler, UIConfiguration::instance().color ("meter marker music"), "bar!", *mtp)); - } else { - metric_marks.push_back (new BBTMarker (*this, *bbt_ruler, UIConfiguration::instance().color ("meter marker"), "foo!", *mtp)); - } - } else if ((ms = dynamic_cast(*i)) != 0) { - snprintf (buf, sizeof(buf), "%d/%d", ms->divisions_per_bar(), ms->note_value ()); - if (ms->map().time_domain() == BeatTime) { - metric_marks.push_back (new MeterMarker (*this, *meter_group, UIConfiguration::instance().color ("meter marker music"), buf, *ms)); - } else { - metric_marks.push_back (new MeterMarker (*this, *meter_group, UIConfiguration::instance().color ("meter marker"), buf, *ms)); - } - } else if ((ts = dynamic_cast(*i)) != 0) { - max_tempo = max (max_tempo, ts->note_types_per_minute()); - max_tempo = max (max_tempo, ts->end_note_types_per_minute()); - min_tempo = min (min_tempo, ts->note_types_per_minute()); - min_tempo = min (min_tempo, ts->end_note_types_per_minute()); - uint32_t const tc_color = UIConfiguration::instance().color ("tempo curve"); + if (mark_point.sclock() < metric_point.sclock()) { - tempo_curves.push_back (new TempoCurve (*this, *tempo_group, tc_color, *ts, ts->sample (sr), false)); + /* advance through markers, deleting the unused ones */ - const std::string tname (X_("")); - if (ts->map().time_domain() == BeatTime) { - metric_marks.push_back (new TempoMarker (*this, *tempo_group, UIConfiguration::instance().color ("tempo marker music"), tname, *ts)); + std::cerr << "\tDeleting marker that doesn't match a tempo point\n"; + delete *mm; + mm = tempo_marks.erase (mm); - } else { - metric_marks.push_back (new TempoMarker (*this, *tempo_group, UIConfiguration::instance().color ("tempo marker"), tname, *ts)); - } - if (prev_ts && abs (prev_ts->end_note_types_per_minute() - ts->note_types_per_minute()) < 1.0) { - metric_marks.back()->set_points_color (UIConfiguration::instance().color ("tempo marker music")); - } else { - metric_marks.back()->set_points_color (UIConfiguration::instance().color ("tempo marker")); - } - prev_ts = ts; + + } else if (metric_point.sclock() < mark_point.sclock()) { + + std::cerr << "\tCreating a marker for " << metric_point << " @ " << metric_point.sample (sr) << " next marker @ " << mark_point.sample (sr) << std::endl; + make_tempo_marker (&metric_point, min_tempo, max_tempo, prev_ts, tc_color, sr); + ++t; + + } else { + /* marker represents an existing point, update text, properties etc */ + /* XXX left/right text stuff */ + // (*mm)->set_name ((*m)->name()); + std::cerr << "\tMoving marker to " << t->time() << std::endl; + (*mm)->set_position (t->time()); + + max_tempo = max (max_tempo, t->note_types_per_minute()); + max_tempo = max (max_tempo, t->end_note_types_per_minute()); + min_tempo = min (min_tempo, t->note_types_per_minute()); + min_tempo = min (min_tempo, t->end_note_types_per_minute()); + + ++t; + ++mm; } - } - tempo_curves.sort (CurveComparator()); + if ((t == tempi.end()) && (mm != tempo_marks.end())) { + while (mm != tempo_marks.end()) { + std::cerr << "\tdrop excess tempo marker @ " << (*mm)->point().time() << std::endl; + delete *mm; + mm = tempo_marks.erase (mm); + } + } + + if ((mm == tempo_marks.end()) && (t != tempi.end())) { + while (t != tempi.end()) { + std::cerr << "\tmake new tempo marker @ " << t->time() << std::endl; + make_tempo_marker (&*t, min_tempo, max_tempo, prev_ts, tc_color, sr); + ++t; + } + } + + update_tempo_curves (min_tempo, max_tempo, sr); + + for (auto & m : tempo_marks) { + TempoMarker* tm = static_cast (m); + tm->update_height_mark ((tm->tempo().note_types_per_minute() - min_tempo) / max (10.0, max_tempo - min_tempo)); + std::cerr << "TEMPO:\n\t" << tm->tempo() << std::endl; + } +} + +void +Editor::draw_meter_marks () +{ + if (!_session) { + return; + } + + Temporal::TempoMap::SharedPtr tmap (TempoMap::use()); + TempoMap::Meters const & meters (tmap->meters()); + TempoMap::Meters::const_iterator m = meters.begin(); + Marks::iterator mm = meter_marks.begin(); + + while (m != meters.end() && mm != meter_marks.end()) { + + Temporal::Point const & mark_point ((*mm)->point()); + Temporal::MeterPoint const & metric_point (*m); + + if (mark_point.sclock() < metric_point.sclock()) { + + /* advance through markers, deleting the unused ones */ + + delete *mm; + mm = meter_marks.erase (mm); + + } else if (metric_point.sclock() < mark_point.sclock()) { + + make_meter_marker (&metric_point); + ++m; + + } else { + /* marker represents an existing point, update text, properties etc */ + /* XXX left/right text stuff */ + // (*mm)->set_name ((*m)->name()); + (*mm)->set_position (m->time()); + ++m; + ++mm; + } + } + + if ((m == meters.end()) && (mm != meter_marks.end())) { + while (mm != meter_marks.end()) { + delete *mm; + mm = meter_marks.erase (mm); + } + } + + if ((mm == tempo_marks.end()) && (m != meters.end())) { + while (m != meters.end()) { + make_meter_marker (&*m); + ++m; + } + } +} + +void +Editor::draw_bbt_marks () +{ + if (!_session) { + return; + } + + Temporal::TempoMap::SharedPtr tmap (TempoMap::use()); + TempoMap::MusicTimes const & bartimes (tmap->bartimes()); + TempoMap::MusicTimes::const_iterator m = bartimes.begin(); + Marks::iterator mm = bbt_marks.begin(); + + while (m != bartimes.end() && mm != bbt_marks.end()) { + + Temporal::Point const & mark_point ((*mm)->point()); + Temporal::MeterPoint const & metric_point (*m); + + if (mark_point.sclock() < metric_point.sclock()) { + + /* advance through markers, deleting the unused ones */ + + delete *mm; + mm = bbt_marks.erase (mm); + + } else if (metric_point.sclock() < mark_point.sclock()) { + + make_meter_marker (&metric_point); + ++m; + + } else { + /* marker represents an existing point, update text, properties etc */ + /* XXX left/right text stuff */ + // (*mm)->set_name ((*m)->name()); + (*mm)->set_position (m->time()); + ++m; + ++mm; + } + } + + if ((m == bartimes.end()) && (mm != bbt_marks.end())) { + while (mm != bbt_marks.end()) { + delete *mm; + mm = bbt_marks.erase (mm); + } + } + + if ((mm == tempo_marks.end()) && (m != bartimes.end())) { + while (m != bartimes.end()) { + make_meter_marker (&*m); + ++m; + } + } +} + +void +Editor::update_tempo_curves (double min_tempo, double max_tempo, samplecnt_t sr) +{ const double min_tempo_range = 5.0; const double tempo_delta = fabs (max_tempo - min_tempo); @@ -229,31 +429,28 @@ Editor::draw_metric_marks (TempoMap::Metrics const & metrics) min_tempo += tempo_delta - min_tempo_range; } - for (Curves::iterator x = tempo_curves.begin(); x != tempo_curves.end(); ) { - Curves::iterator tmp = x; - (*x)->set_max_tempo (max_tempo); - (*x)->set_min_tempo (min_tempo); + for (Marks::iterator m = tempo_marks.begin(); m != tempo_marks.end(); ++m) { + + TempoMarker* tm = static_cast(*m); + Marks::iterator tmp = m; ++tmp; - if (tmp != tempo_curves.end()) { - (*x)->set_position ((*x)->tempo().sample(sr), (*tmp)->tempo().sample(sr)); + + TempoCurve& curve (tm->curve()); + + curve.set_max_tempo (max_tempo); + curve.set_min_tempo (min_tempo); + + if (tmp != tempo_marks.end()) { + TempoMarker* nxt = static_cast(*tmp); + curve.set_duration (nxt->tempo().sample(sr) - tm->tempo().sample(sr)); } else { - (*x)->set_position ((*x)->tempo().sample(sr), UINT32_MAX); + curve.set_duration (samplecnt_t (UINT32_MAX)); } - if (!(*x)->tempo().active()) { - (*x)->hide(); + if (!tm->tempo().active()) { + curve.hide(); } else { - (*x)->show(); - } - - ++x; - } - - for (Marks::iterator x = metric_marks.begin(); x != metric_marks.end(); ++x) { - TempoMarker* tempo_marker; - - if ((tempo_marker = dynamic_cast (*x)) != 0) { - tempo_marker->update_height_mark ((tempo_marker->tempo().note_types_per_minute() - min_tempo) / max (10.0, max_tempo - min_tempo)); + curve.show(); } } } @@ -294,12 +491,13 @@ Editor::tempo_curve_selected (Temporal::TempoPoint const * ts, bool yn) return; } - for (Curves::iterator x = tempo_curves.begin(); x != tempo_curves.end(); ++x) { - if (&(*x)->tempo() == ts) { + for (Marks::iterator x = tempo_marks.begin(); x != tempo_marks.end(); ++x) { + TempoMarker* tm = static_cast (*x); + if (&tm->tempo() == ts) { if (yn) { - (*x)->set_color_rgba (UIConfiguration::instance().color ("location marker")); + tm->curve().set_color_rgba (UIConfiguration::instance().color ("location marker")); } else { - (*x)->set_color_rgba (UIConfiguration::instance().color ("tempo curve")); + tm->curve().set_color_rgba (UIConfiguration::instance().color ("tempo curve")); } break; } @@ -565,17 +763,17 @@ Editor::edit_tempo_section (TempoPoint& section) void Editor::edit_tempo_marker (TempoMarker& tm) { - edit_tempo_section (tm.tempo()); + edit_tempo_section (const_cast(tm.tempo())); } void Editor::edit_meter_marker (MeterMarker& mm) { - edit_meter_section (mm.meter()); + edit_meter_section (const_cast(mm.meter())); } gint -Editor::real_remove_tempo_marker (TempoPoint *section) +Editor::real_remove_tempo_marker (TempoPoint const * section) { begin_reversible_command (_("remove tempo mark")); TempoMap::SharedPtr tmap (TempoMap::write_copy()); @@ -612,7 +810,7 @@ Editor::remove_meter_marker (ArdourCanvas::Item* item) } gint -Editor::real_remove_meter_marker (Temporal::MeterPoint *section) +Editor::real_remove_meter_marker (Temporal::MeterPoint const * section) { begin_reversible_command (_("remove tempo mark")); TempoMap::SharedPtr tmap (TempoMap::write_copy()); @@ -651,3 +849,10 @@ Editor::commit_tempo_map_edit () TempoMap::SharedPtr tmap (TempoMap::use()); TempoMap::update (tmap); } + +void +Editor::mid_tempo_change () +{ + std::cerr << "============== MID TEMPO\n"; + draw_tempo_marks (); +} diff --git a/gtk2_ardour/marker.cc b/gtk2_ardour/marker.cc index fdda34b748..910fc2e79c 100644 --- a/gtk2_ardour/marker.cc +++ b/gtk2_ardour/marker.cc @@ -51,6 +51,7 @@ #include "public_editor.h" #include "utils.h" #include "rgb_macros.h" +#include "tempo_curve.h" #include @@ -535,6 +536,7 @@ void ArdourMarker::set_position (timepos_t const & pos) { unit_position = editor.sample_to_pixel (pos.samples()) - _shift; + cerr << "marker @ " << this << " set pos to " << unit_position << endl; group->set_x_position (unit_position); setup_line (); _position = pos; @@ -631,18 +633,32 @@ ArdourMarker::set_right_label_limit (double p) } } +MetricMarker::MetricMarker (PublicEditor& ed, ArdourCanvas::Item& parent, guint32 rgba, const string& annotation, + Type type, timepos_t const & pos, bool handle_events) + : ArdourMarker (ed, parent, rgba, annotation, type, pos, false) +{ +} + /***********************************************************************/ -TempoMarker::TempoMarker (PublicEditor& editor, ArdourCanvas::Item& parent, guint32 rgba, const string& text, - Temporal::TempoPoint& temp) - : ArdourMarker (editor, parent, rgba, text, Tempo, temp.time(), false) +TempoMarker::TempoMarker (PublicEditor& editor, ArdourCanvas::Item& parent, guint32 rgba, const string& text, Temporal::TempoPoint const & temp, samplepos_t sample, uint32_t curve_color) + : MetricMarker (editor, parent, rgba, text, Tempo, temp.time(), false) , _tempo (&temp) { group->Event.connect (sigc::bind (sigc::mem_fun (editor, &PublicEditor::canvas_tempo_marker_event), group, this)); + /* points[1].x gives the width of the marker */ + _curve = new TempoCurve (editor, *group, curve_color, temp, true, (*points)[1].x); } TempoMarker::~TempoMarker () { + delete _curve; +} + +TempoCurve& +TempoMarker::curve() +{ + return *_curve; } void @@ -666,16 +682,21 @@ TempoMarker::update_height_mark (const double ratio) } void -TempoMarker::reset_tempo (Temporal::TempoPoint & t) +TempoMarker::reset_tempo (Temporal::TempoPoint const & t) { _tempo = &t; } +Temporal::Point const & +TempoMarker::point() const +{ + return *_tempo; +} /***********************************************************************/ -MeterMarker::MeterMarker (PublicEditor& editor, ArdourCanvas::Item& parent, guint32 rgba, const string& text, Temporal::MeterPoint& m) - : ArdourMarker (editor, parent, rgba, text, Meter, m.time(), false) +MeterMarker::MeterMarker (PublicEditor& editor, ArdourCanvas::Item& parent, guint32 rgba, const string& text, Temporal::MeterPoint const & m) + : MetricMarker (editor, parent, rgba, text, Meter, m.time(), false) , _meter (&m) { group->Event.connect (sigc::bind (sigc::mem_fun (editor, &PublicEditor::canvas_meter_marker_event), group, this)); @@ -686,15 +707,21 @@ MeterMarker::~MeterMarker () } void -MeterMarker::reset_meter (Temporal::MeterPoint & m) +MeterMarker::reset_meter (Temporal::MeterPoint const & m) { _meter = &m; } +Temporal::Point const & +MeterMarker::point() const +{ + return *_meter; +} + /***********************************************************************/ -BBTMarker::BBTMarker (PublicEditor& editor, ArdourCanvas::Item& parent, guint32 rgba, const string& text, Temporal::MusicTimePoint& p) - : ArdourMarker (editor, parent, rgba, text, BBTPosition, p.time(), false) +BBTMarker::BBTMarker (PublicEditor& editor, ArdourCanvas::Item& parent, guint32 rgba, const string& text, Temporal::MusicTimePoint const & p) + : MetricMarker (editor, parent, rgba, text, BBTPosition, p.time(), false) , _point (&p) { group->Event.connect (sigc::bind (sigc::mem_fun (editor, &PublicEditor::canvas_bbt_marker_event), group, this)); @@ -705,7 +732,13 @@ BBTMarker::~BBTMarker () } void -BBTMarker::reset_point (Temporal::MusicTimePoint & p) +BBTMarker::reset_point (Temporal::MusicTimePoint const & p) { _point = &p; } + +Temporal::Point const & +BBTMarker::point() const +{ + return *_point; +} diff --git a/gtk2_ardour/marker.h b/gtk2_ardour/marker.h index 7cef154858..dd67b14780 100644 --- a/gtk2_ardour/marker.h +++ b/gtk2_ardour/marker.h @@ -36,6 +36,7 @@ #include "canvas/types.h" namespace Temporal { + class Point; class TempoPoint; class MeterPoint; class MusicTimePoint; @@ -43,6 +44,7 @@ namespace Temporal { class PublicEditor; class RegionView; +class TempoCurve; /** Location Marker * @@ -156,47 +158,60 @@ private: ArdourMarker & operator= (ArdourMarker const &); }; -class TempoMarker : public ArdourMarker +class MetricMarker : public ArdourMarker { public: - TempoMarker (PublicEditor& editor, ArdourCanvas::Item &, guint32 rgba, const std::string& text, Temporal::TempoPoint&); + MetricMarker (PublicEditor& ed, ArdourCanvas::Item& parent, guint32 rgba, const std::string& annotation, Type type, Temporal::timepos_t const & pos, bool handle_events); + virtual Temporal::Point const & point() const = 0; +}; + +class TempoMarker : public MetricMarker +{ + public: + TempoMarker (PublicEditor& editor, ArdourCanvas::Item &, guint32 rgba, const std::string& text, Temporal::TempoPoint const &, samplepos_t sample, uint32_t curve_color); ~TempoMarker (); - void reset_tempo (Temporal::TempoPoint & t); + void reset_tempo (Temporal::TempoPoint const & t); - Temporal::TempoPoint& tempo() const { return *_tempo; } + Temporal::TempoPoint const & tempo() const { return *_tempo; } + Temporal::Point const & point() const; void update_height_mark (const double ratio); + TempoCurve& curve(); + private: - Temporal::TempoPoint* _tempo; + Temporal::TempoPoint const * _tempo; + TempoCurve* _curve; }; -class MeterMarker : public ArdourMarker +class MeterMarker : public MetricMarker { public: - MeterMarker (PublicEditor& editor, ArdourCanvas::Item &, guint32 rgba, const std::string& text, Temporal::MeterPoint&); + MeterMarker (PublicEditor& editor, ArdourCanvas::Item &, guint32 rgba, const std::string& text, Temporal::MeterPoint const &); ~MeterMarker (); - void reset_meter (Temporal::MeterPoint & m); + void reset_meter (Temporal::MeterPoint const & m); - Temporal::MeterPoint& meter() const { return *_meter; } + Temporal::MeterPoint const & meter() const { return *_meter; } + Temporal::Point const & point() const; private: - Temporal::MeterPoint* _meter; + Temporal::MeterPoint const * _meter; }; -class BBTMarker : public ArdourMarker +class BBTMarker : public MetricMarker { public: - BBTMarker (PublicEditor& editor, ArdourCanvas::Item &, guint32 rgba, const std::string& text, Temporal::MusicTimePoint&); + BBTMarker (PublicEditor& editor, ArdourCanvas::Item &, guint32 rgba, const std::string& text, Temporal::MusicTimePoint const &); ~BBTMarker (); - void reset_point (Temporal::MusicTimePoint &); + void reset_point (Temporal::MusicTimePoint const &); - Temporal::MusicTimePoint& point() const { return *_point; } + Temporal::MusicTimePoint const & mt_point() const { return *_point; } + Temporal::Point const & point() const; private: - Temporal::MusicTimePoint* _point; + Temporal::MusicTimePoint const * _point; }; #endif /* __gtk_ardour_marker_h__ */ diff --git a/gtk2_ardour/slot_properties_box.cc b/gtk2_ardour/slot_properties_box.cc index 036f095864..9bfb1a4b95 100644 --- a/gtk2_ardour/slot_properties_box.cc +++ b/gtk2_ardour/slot_properties_box.cc @@ -238,7 +238,6 @@ SlotPropertyTable::SlotPropertyTable () set_homogeneous (false); int row=0; - Gtk::Label *label; /* ---- Basic trigger properties (name, color) ----- */ _trigger_table.set_spacings (4); @@ -259,20 +258,20 @@ SlotPropertyTable::SlotPropertyTable () _launch_table.set_homogeneous (false); row=0; - label = manage(new Gtk::Label(_("Velocity Sense:"))); label->set_alignment(1.0, 0.5); - _launch_table.attach(*label, 0, 1, row, row+1, Gtk::FILL, Gtk::SHRINK ); + _vel_sense_label.set_text(_("Velocity Sense:")); _vel_sense_label.set_alignment(1.0, 0.5); + _launch_table.attach(_vel_sense_label, 0, 1, row, row+1, Gtk::FILL, Gtk::SHRINK ); _launch_table.attach(_velocity_slider, 1, 3, row, row+1, Gtk::FILL, Gtk::SHRINK ); row++; - label = manage(new Gtk::Label(_("Launch Style:"))); label->set_alignment(1.0, 0.5); - _launch_table.attach(*label, 0, 1, row, row+1, Gtk::FILL, Gtk::SHRINK ); + _launch_style_label.set_text(_("Launch Style:")); _launch_style_label.set_alignment(1.0, 0.5); + _launch_table.attach(_launch_style_label, 0, 1, row, row+1, Gtk::FILL, Gtk::SHRINK ); _launch_table.attach(_launch_style_button, 1, 3, row, row+1, Gtk::FILL, Gtk::SHRINK ); row++; - label = manage(new Gtk::Label(_("Launch Quantize:"))); label->set_alignment(1.0, 0.5); - _launch_table.attach(*label, 0, 1, row, row+1, Gtk::FILL, Gtk::SHRINK ); - _launch_table.attach(_quantize_button, 1, 3, row, row+1, Gtk::FILL, Gtk::SHRINK ); row++; + _launch_quant_label.set_text(_("Launch Quantize:")); _launch_quant_label.set_alignment(1.0, 0.5); + _launch_table.attach(_launch_quant_label, 0, 1, row, row+1, Gtk::FILL, Gtk::SHRINK ); + _launch_table.attach(_quantize_button, 1, 3, row, row+1, Gtk::FILL, Gtk::SHRINK ); row++; - label = manage(new Gtk::Label(_("Legato Mode:"))); label->set_alignment(1.0, 0.5); - _launch_table.attach(*label, 0, 1, row, row+1, Gtk::FILL, Gtk::SHRINK ); + _legato_label.set_text(_("Launch Quantize:")); _legato_label.set_alignment(1.0, 0.5); + _launch_table.attach(_legato_label, 0, 1, row, row+1, Gtk::FILL, Gtk::SHRINK ); _launch_table.attach(_legato_button, 1, 3, row, row+1, Gtk::FILL, Gtk::SHRINK ); row++; @@ -299,21 +298,20 @@ SlotPropertyTable::SlotPropertyTable () fol_table->set_spacings(2); fol_table->set_border_width(4); - label = manage(new Gtk::Label(_("Follow Count:"))); label->set_alignment(1.0, 0.5); - fol_table->attach(*label, 1, 2, row, row+1, Gtk::FILL, Gtk::SHRINK ); + _follow_count_label.set_text(_("Follow Count:")); _follow_count_label.set_alignment(1.0, 0.5); + fol_table->attach(_follow_count_label, 1, 2, row, row+1, Gtk::FILL, Gtk::SHRINK ); Gtk::Alignment *align = manage (new Gtk::Alignment (0, .5, 0, 0)); align->add (_follow_count_spinner); - fol_table->attach(*align, 2, 3, row, row+1, Gtk::FILL, Gtk::SHRINK, 0, 0 ); row++; + fol_table->attach(*align, 2, 3, row, row+1, Gtk::FILL, Gtk::SHRINK, 0, 0 ); row++; - label = manage(new Gtk::Label(_("Follow Length:"))); label->set_alignment(1.0, 0.5); - Gtk::Label *beat_label = manage (new Gtk::Label (_("(beats)"))); - beat_label->set_alignment (0.0, 0.5); + _follow_length_label.set_text(_("Follow Length:")); _follow_length_label.set_alignment(1.0, 0.5); + _beat_label.set_text(_("(beats)")); _beat_label.set_alignment (0.0, 0.5); Gtk::Alignment *fl_align = manage (new Gtk::Alignment (0, .5, 0, 0)); fl_align->add (_follow_length_spinner); fol_table->attach(_use_follow_length_button, 0, 1, row, row+1, Gtk::SHRINK, Gtk::SHRINK); - fol_table->attach(*label, 1, 2, row, row+1, Gtk::FILL, Gtk::SHRINK ); + fol_table->attach(_follow_length_label, 1, 2, row, row+1, Gtk::FILL, Gtk::SHRINK ); fol_table->attach(*fl_align, 2, 3, row, row+1, Gtk::FILL, Gtk::SHRINK ); - fol_table->attach(*beat_label, 3, 4, row, row+1, Gtk::SHRINK, Gtk::SHRINK); + fol_table->attach(_beat_label, 3, 4, row, row+1, Gtk::SHRINK, Gtk::SHRINK); _follow_table.attach(_follow_left, 0, 1, row, row+1, Gtk::FILL, Gtk::SHRINK ); _follow_table.attach(_follow_right, 1, 2, row, row+1, Gtk::FILL, Gtk::SHRINK ); row++; @@ -537,7 +535,33 @@ SlotPropertyTable::on_trigger_changed (PropertyChange const& pc) } if (pc.contains (Properties::follow_action0)) { - _follow_left.set_text (follow_action_to_string (trigger()->follow_action (0))); + _follow_left.set_text (follow_action_to_string (trigger()->follow_action (0))); + + /* set widget sensitivity based on 'left' follow action */ + bool follow_widgets_sensitive = trigger()->follow_action (0) != Trigger::None; + if (follow_widgets_sensitive) { + _follow_right.set_sensitive(true); + _follow_count_spinner.set_sensitive(true); + _follow_length_spinner.set_sensitive(true); + _use_follow_length_button.set_sensitive(true); + _follow_probability_slider.set_sensitive(true); + _left_probability_label.set_sensitive(true); + _right_probability_label.set_sensitive(true); + _beat_label.set_sensitive(true); + _follow_count_label.set_sensitive(true); + _follow_length_label.set_sensitive(true); + } else { + _follow_right.set_sensitive(false); + _follow_count_spinner.set_sensitive(false); + _follow_length_spinner.set_sensitive(false); + _use_follow_length_button.set_sensitive(false); + _follow_probability_slider.set_sensitive(false); + _left_probability_label.set_sensitive(false); + _right_probability_label.set_sensitive(false); + _beat_label.set_sensitive(false); + _follow_count_label.set_sensitive(false); + _follow_length_label.set_sensitive(false); + } } if (pc.contains (Properties::follow_action1)) { @@ -554,22 +578,6 @@ SlotPropertyTable::on_trigger_changed (PropertyChange const& pc) _right_probability_label.set_text (string_compose(_("%1%% Right"), probability)); } - bool follow_widgets_sensitive = trigger()->follow_action (0) != Trigger::None; - - if (follow_widgets_sensitive) { - _follow_right.set_sensitive(true); - _follow_count_spinner.set_sensitive(true); - _follow_length_spinner.set_sensitive(true); - _use_follow_length_button.set_sensitive(true); - _follow_probability_slider.set_sensitive(true); - } else { - _follow_right.set_sensitive(false); - _follow_count_spinner.set_sensitive(false); - _follow_length_spinner.set_sensitive(false); - _use_follow_length_button.set_sensitive(false); - _follow_probability_slider.set_sensitive(false); - } - _ignore_changes = false; } diff --git a/gtk2_ardour/slot_properties_box.h b/gtk2_ardour/slot_properties_box.h index 9a76d09f1c..df2c9acc55 100644 --- a/gtk2_ardour/slot_properties_box.h +++ b/gtk2_ardour/slot_properties_box.h @@ -77,6 +77,10 @@ class SlotPropertyTable : public TriggerUI, public Gtk::Table Gtk::SpinButton _gain_spinner; Gtk::Label _gain_label; + Gtk::Label _beat_label; + Gtk::Label _follow_length_label; + Gtk::Label _follow_count_label; + Gtk::Label _left_probability_label; Gtk::Label _right_probability_label; Gtk::Adjustment _follow_probability_adjustment; @@ -92,6 +96,11 @@ class SlotPropertyTable : public TriggerUI, public Gtk::Table ArdourWidgets::ArdourDropdown _follow_left; ArdourWidgets::ArdourDropdown _follow_right; + Gtk::Label _vel_sense_label; + Gtk::Label _launch_style_label; + Gtk::Label _launch_quant_label; + Gtk::Label _legato_label; + ArdourWidgets::ArdourButton _legato_button; ArdourWidgets::ArdourDropdown _quantize_button; diff --git a/gtk2_ardour/tempo_curve.cc b/gtk2_ardour/tempo_curve.cc index 739b6c7251..713e326eab 100644 --- a/gtk2_ardour/tempo_curve.cc +++ b/gtk2_ardour/tempo_curve.cc @@ -44,17 +44,21 @@ PBD::Signal1 TempoCurve::CatchDeletion; static double curve_height = 13.0; -void TempoCurve::setup_sizes(const double timebar_height) +void +TempoCurve::setup_sizes(const double timebar_height) { - curve_height = floor (timebar_height) - 2.5; + const double ui_scale = UIConfiguration::instance ().get_ui_scale (); + curve_height = floor (timebar_height) - (2.5 * ui_scale); } + /* ignores Tempo note type - only note_types_per_minute is potentially curved */ -TempoCurve::TempoCurve (PublicEditor& ed, ArdourCanvas::Container& parent, guint32 rgba, TempoPoint& temp, samplepos_t sample, bool handle_events) +TempoCurve::TempoCurve (PublicEditor& ed, ArdourCanvas::Item& parent, guint32 rgba, TempoPoint const & temp, bool handle_events, ArdourCanvas::Distance marker_width) : editor (ed) , _parent (&parent) , _curve (0) - , _shown (false) + , _duration (UINT32_MAX) + , _marker_width (marker_width) , _color (rgba) , _min_tempo (temp.note_types_per_minute()) , _max_tempo (temp.note_types_per_minute()) @@ -62,10 +66,8 @@ TempoCurve::TempoCurve (PublicEditor& ed, ArdourCanvas::Container& parent, guint , _start_text (0) , _end_text (0) { - sample_position = sample; - unit_position = editor.sample_to_pixel (sample); - - group = new ArdourCanvas::Container (&parent, ArdourCanvas::Duple (unit_position, 1)); + /* XXX x arg for Duple should probably be marker width, passed in from owner */ + group = new ArdourCanvas::Container (&parent, ArdourCanvas::Duple (marker_width, 1)); #ifdef CANVAS_DEBUG group->name = string_compose ("TempoCurve::group for %1", _tempo.note_types_per_minute()); #endif @@ -75,8 +77,7 @@ TempoCurve::TempoCurve (PublicEditor& ed, ArdourCanvas::Container& parent, guint _curve->name = string_compose ("TempoCurve::curve for %1", _tempo.note_types_per_minute()); #endif _curve->set_points_per_segment (3); - points = new ArdourCanvas::Points (); - _curve->set (*points); + _curve->set (points); _start_text = new ArdourCanvas::Text (group); _end_text = new ArdourCanvas::Text (group); @@ -116,18 +117,6 @@ TempoCurve::~TempoCurve () 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 { @@ -135,42 +124,31 @@ TempoCurve::the_item() const } void -TempoCurve::set_position (samplepos_t sample, samplepos_t end_sample) +TempoCurve::set_duration (samplecnt_t duration) { - unit_position = editor.sample_to_pixel (sample); - group->set_x_position (unit_position); - sample_position = sample; - _end_sample = end_sample; + points.clear(); + points.push_back (ArdourCanvas::Duple (0.0, curve_height)); - points->clear(); - points = new ArdourCanvas::Points (); + ArdourCanvas::Coord duration_pixels = editor.sample_to_pixel (duration); - points->push_back (ArdourCanvas::Duple (0.0, curve_height)); + if (!_tempo.ramped()) { - if (sample >= end_sample) { - /* shouldn't happen but ..*/ const double tempo_at = _tempo.note_types_per_minute(); const double y_pos = (curve_height) - (((tempo_at - _min_tempo) / (_max_tempo - _min_tempo)) * curve_height); - points->push_back (ArdourCanvas::Duple (0.0, y_pos)); - points->push_back (ArdourCanvas::Duple (1.0, y_pos)); + points.push_back (ArdourCanvas::Duple (0.0, y_pos)); + points.push_back (ArdourCanvas::Duple (duration_pixels, y_pos)); - } else if (!_tempo.ramped()) { - const double tempo_at = _tempo.note_types_per_minute(); - const double y_pos = (curve_height) - (((tempo_at - _min_tempo) / (_max_tempo - _min_tempo)) * curve_height); - - points->push_back (ArdourCanvas::Duple (0.0, y_pos)); - points->push_back (ArdourCanvas::Duple (editor.sample_to_pixel (end_sample - sample), y_pos)); } else { - const samplepos_t sample_step = std::max ((end_sample - sample) / 5, (samplepos_t) 1); - samplepos_t current_sample = sample; + const samplepos_t sample_step = std::max ((duration) / 5, (samplepos_t) 1); + samplepos_t current_sample = 0; - while (current_sample < end_sample) { + while (current_sample < duration) { const double tempo_at = _tempo.note_types_per_minute_at_DOUBLE (timepos_t (current_sample)); const double y_pos = std::max ((curve_height) - (((tempo_at - _min_tempo) / (_max_tempo - _min_tempo)) * curve_height), 0.0); - points->push_back (ArdourCanvas::Duple (editor.sample_to_pixel (current_sample - sample), std::min (y_pos, curve_height))); + points.push_back (ArdourCanvas::Duple (editor.sample_to_pixel (current_sample), std::min (y_pos, curve_height))); current_sample += sample_step; } @@ -178,48 +156,49 @@ TempoCurve::set_position (samplepos_t sample, samplepos_t end_sample) const double tempo_at = _tempo.note_types_per_minute(); const double y_pos = std::max ((curve_height) - (((tempo_at - _min_tempo) / (_max_tempo - _min_tempo)) * curve_height), 0.0); - points->push_back (ArdourCanvas::Duple (editor.sample_to_pixel (end_sample - sample), std::min (y_pos, curve_height))); + points.push_back (ArdourCanvas::Duple (duration_pixels, std::min (y_pos, curve_height))); } - _curve->set (*points); + _curve->set (points); char buf[10]; + snprintf (buf, sizeof (buf), "%.3f/%d", _tempo.note_types_per_minute(), _tempo.note_type()); _start_text->set (buf); snprintf (buf, sizeof (buf), "%.3f", _tempo.end_note_types_per_minute()); _end_text->set (buf); - _start_text->set_position (ArdourCanvas::Duple (10, .5 )); - _end_text->set_position (ArdourCanvas::Duple (editor.sample_to_pixel (end_sample - sample) - _end_text->text_width() - 10, .5 )); + const double ui_scale = UIConfiguration::instance ().get_ui_scale (); - if (_end_text->text_width() + _start_text->text_width() + 20 > editor.sample_to_pixel (end_sample - sample)) { + _start_text->set_position (ArdourCanvas::Duple (_marker_width + (10 * ui_scale), (.5 * ui_scale))); + _end_text->set_position (ArdourCanvas::Duple (duration_pixels - _end_text->text_width() - _marker_width - (10. * ui_scale), (.5 * ui_scale))); + + if (_end_text->text_width() + _start_text->text_width() + (20.0 * ui_scale) > duration_pixels) { _start_text->hide(); _end_text->hide(); } else { _start_text->show(); _end_text->show(); } + + _duration = duration; } void TempoCurve::reposition () { - set_position (sample_position, _end_sample); + set_duration (_duration); } void TempoCurve::show () { - _shown = true; - group->show (); } void TempoCurve::hide () { - _shown = false; - group->hide (); } diff --git a/gtk2_ardour/tempo_curve.h b/gtk2_ardour/tempo_curve.h index 956426d3c4..272769858e 100644 --- a/gtk2_ardour/tempo_curve.h +++ b/gtk2_ardour/tempo_curve.h @@ -40,7 +40,7 @@ class PublicEditor; class TempoCurve : public sigc::trackable { public: - TempoCurve (PublicEditor& editor, ArdourCanvas::Container &, guint32 rgba, Temporal::TempoPoint& temp, samplepos_t sample, bool handle_events); + TempoCurve (PublicEditor& editor, ArdourCanvas::Item &, guint32 rgba, Temporal::TempoPoint const & temp, bool handle_events , ArdourCanvas::Distance marker_width); ~TempoCurve (); static PBD::Signal1 CatchDeletion; @@ -48,19 +48,14 @@ public: static void setup_sizes (const double timebar_height); ArdourCanvas::Item& the_item() const; - void canvas_height_set (double); - void set_position (samplepos_t lower, samplepos_t upper); + void set_duration (ARDOUR::samplecnt_t duration); void set_color_rgba (uint32_t rgba); - samplepos_t position() const { return sample_position; } - - ArdourCanvas::Container* get_parent() { return _parent; } - void reparent (ArdourCanvas::Container& parent); void hide (); void show (); - Temporal::TempoPoint& tempo () const { return _tempo; } + Temporal::TempoPoint const & tempo () const { return _tempo; } void set_max_tempo (const double& max) { _max_tempo = max; } void set_min_tempo (const double& min) { _min_tempo = min; } @@ -68,17 +63,14 @@ public: protected: PublicEditor& editor; - ArdourCanvas::Container* _parent; + ArdourCanvas::Item* _parent; ArdourCanvas::Container* group; - ArdourCanvas::Points* points; + ArdourCanvas::Points points; ArdourCanvas::FramedCurve* _curve; - double unit_position; - samplepos_t sample_position; - samplepos_t _end_sample; - bool _shown; - double _canvas_height; - uint32_t _color; + ARDOUR::samplecnt_t _duration; + ArdourCanvas::Distance _marker_width; + uint32_t _color; void reposition (); @@ -91,7 +83,7 @@ private: double _min_tempo; double _max_tempo; - Temporal::TempoPoint& _tempo; + Temporal::TempoPoint const & _tempo; ArdourCanvas::Text* _start_text; ArdourCanvas::Text* _end_text; }; diff --git a/gtk2_ardour/trigger_master.cc b/gtk2_ardour/trigger_master.cc index cf8e1f61ea..19f71dcf67 100644 --- a/gtk2_ardour/trigger_master.cc +++ b/gtk2_ardour/trigger_master.cc @@ -192,13 +192,6 @@ TriggerMaster::TriggerMaster (Item* parent) Event.connect (sigc::mem_fun (*this, &TriggerMaster::event_handler)); - stop_shape = new ArdourCanvas::Polygon (this); - stop_shape->set_outline (true); - stop_shape->set_fill (false); - stop_shape->name = X_("stopbutton"); - stop_shape->set_ignore_events (true); - stop_shape->show (); - name_text = new Text (this); name_text->set (""); name_text->set_ignore_events (false); @@ -309,7 +302,6 @@ TriggerMaster::event_handler (GdkEvent* ev) case GDK_ENTER_NOTIFY: if (ev->crossing.detail != GDK_NOTIFY_INFERIOR) { name_text->set_color (UIConfiguration::instance ().color ("neutral:foregroundest")); - stop_shape->set_outline_color (UIConfiguration::instance ().color ("neutral:midground")); set_fill_color (HSV (fill_color ()).lighter (0.15).color ()); } redraw (); @@ -501,12 +493,6 @@ TriggerMaster::_size_allocate (ArdourCanvas::Rect const& alloc) _poly_size = height - (_poly_margin * 2); - Points p; - p.push_back (Duple (_poly_margin, _poly_size)); - p.push_back (Duple (_poly_size, _poly_size)); - p.push_back (Duple (0.5 + _poly_size / 2, _poly_margin )); - stop_shape->set (p); - float tleft = _poly_size + (_poly_margin * 3); float twidth = width - _poly_size - (_poly_margin * 3); @@ -537,7 +523,6 @@ TriggerMaster::prop_change (PropertyChange const& change) if (!trigger) { name_text->set (text); _loopster->hide (); - stop_shape->show (); return; } @@ -553,19 +538,16 @@ TriggerMaster::prop_change (PropertyChange const& change) double f = trigger->position_as_fraction (); _loopster->set_fraction (f); _loopster->show (); - stop_shape->hide (); } else { _loopster->hide (); - stop_shape->show (); } } void TriggerMaster::set_default_colors () { - set_fill_color (HSV (UIConfiguration::instance ().color ("theme:bg")).darker (0.25).color ()); + set_fill_color (HSV (UIConfiguration::instance ().color ("theme:bg")).darker (0.5).color ()); name_text->set_color (UIConfiguration::instance ().color ("neutral:foreground")); - stop_shape->set_outline_color (fill_color()); } void @@ -588,15 +570,11 @@ CueMaster::CueMaster (Item* parent) stop_shape = new ArdourCanvas::Polygon (this); stop_shape->set_outline (true); - stop_shape->set_fill (false); + stop_shape->set_fill (true); stop_shape->name = X_("stopbutton"); stop_shape->set_ignore_events (true); stop_shape->show (); - name_text = new Text (this); - name_text->set (""); - name_text->set_ignore_events (false); - /* prefs (theme colors) */ UIConfiguration::instance ().ParameterChanged.connect (sigc::mem_fun (*this, &CueMaster::ui_parameter_changed)); set_default_colors (); @@ -666,9 +644,9 @@ CueMaster::event_handler (GdkEvent* ev) break; case GDK_ENTER_NOTIFY: if (ev->crossing.detail != GDK_NOTIFY_INFERIOR) { - name_text->set_color (UIConfiguration::instance ().color ("neutral:foregroundest")); stop_shape->set_outline_color (UIConfiguration::instance ().color ("neutral:foreground")); - set_fill_color (HSV (fill_color ()).lighter (0.15).color ()); + stop_shape->set_fill_color (UIConfiguration::instance ().color ("neutral:foreground")); + set_fill_color (HSV (fill_color ()).lighter (0.25).color ()); } break; case GDK_LEAVE_NOTIFY: @@ -710,22 +688,14 @@ CueMaster::_size_allocate (ArdourCanvas::Rect const& alloc) float tleft = _poly_size + (_poly_margin * 3); float twidth = width - _poly_size - (_poly_margin * 3); - - ArdourCanvas::Rect text_alloc (tleft, 0, twidth, height); // testing - name_text->size_allocate (text_alloc); - name_text->set_position (Duple (tleft, 1. * scale)); - name_text->clamp_width (twidth); - - /* font scale may have changed. uiconfig 'embeds' the ui-scale in the font */ - name_text->set_font_description (UIConfiguration::instance ().get_NormalFont ()); } void CueMaster::set_default_colors () { - set_fill_color (HSV (UIConfiguration::instance ().color ("theme:bg")).darker (0.25).color ()); - name_text->set_color (UIConfiguration::instance ().color ("neutral:foreground")); + set_fill_color (HSV (UIConfiguration::instance ().color ("theme:bg")).darker (0.5).color ()); stop_shape->set_outline_color (UIConfiguration::instance ().color ("neutral:foreground")); + stop_shape->set_fill_color (fill_color()); } void diff --git a/gtk2_ardour/trigger_master.h b/gtk2_ardour/trigger_master.h index c9814cc450..a179f18e0d 100644 --- a/gtk2_ardour/trigger_master.h +++ b/gtk2_ardour/trigger_master.h @@ -74,7 +74,6 @@ public: void _size_allocate (ArdourCanvas::Rect const&); ArdourCanvas::Text* name_text; - ArdourCanvas::Polygon* stop_shape; void toggle_thru (); void maybe_update (); @@ -126,7 +125,6 @@ public: void _size_allocate (ArdourCanvas::Rect const& alloc); ArdourCanvas::Polygon* stop_shape; - ArdourCanvas::Text* name_text; void maybe_update (); bool event_handler (GdkEvent*); diff --git a/gtk2_ardour/trigger_page.cc b/gtk2_ardour/trigger_page.cc index ae19c1c1c1..d31aa03ce5 100644 --- a/gtk2_ardour/trigger_page.cc +++ b/gtk2_ardour/trigger_page.cc @@ -144,9 +144,11 @@ TriggerPage::TriggerPage () table->attach (_audio_trig_box, col, col + 1, 0, 1, Gtk::FILL, Gtk::SHRINK); ++col; +#if MIDI_PROPERTIES_BOX_IMPLEMENTED col = 2; table->attach (_midi_trig_box, col, col + 1, 0, 1, Gtk::FILL, Gtk::SHRINK); ++col; +#endif _parameter_box.pack_start (*table); diff --git a/gtk2_ardour/trigger_ui.cc b/gtk2_ardour/trigger_ui.cc index 8d0e509de2..478e745be0 100644 --- a/gtk2_ardour/trigger_ui.cc +++ b/gtk2_ardour/trigger_ui.cc @@ -730,7 +730,7 @@ TriggerUI::launch_style_to_string (Trigger::LaunchStyle ls) { switch (ls) { case Trigger::OneShot: - return _("One Shot"); + return _("Trigger"); case Trigger::ReTrigger: return _("Retrigger"); case Trigger::Gate: diff --git a/gtk2_ardour/triggerbox_ui.cc b/gtk2_ardour/triggerbox_ui.cc index 11d4fdc376..a6293e4dcc 100644 --- a/gtk2_ardour/triggerbox_ui.cc +++ b/gtk2_ardour/triggerbox_ui.cc @@ -166,9 +166,11 @@ TriggerEntry::_size_allocate (ArdourCanvas::Rect const& alloc) _poly_margin = 2. * scale; _poly_size = height - 2 * _poly_margin; - name_text->size_allocate (ArdourCanvas::Rect (0, 0, width, height - _poly_margin * 2)); + float font_margin = 2. * scale; + + name_text->size_allocate (ArdourCanvas::Rect (0, 0, width, height - font_margin * 2)); float tleft = height; // make room for the play button - name_text->set_position (Duple (tleft + _poly_margin, _poly_margin)); // @paul why do we need tleft here? isn't name_text a child of name_button? + name_text->set_position (Duple (tleft + _poly_margin, font_margin)); // @paul why do we need tleft here? isn't name_text a child of name_button? name_text->clamp_width (width - height * 2 - _poly_margin * 3); /* font scale may have changed. uiconfig 'embeds' the ui-scale in the font */ @@ -471,7 +473,7 @@ TriggerEntry::render (ArdourCanvas::Rect const& area, Cairo::RefPtrset_identity_matrix (); } - if (tref.slot == 1) { + if (false /*tref.slot == 1*/) { /* drop-shadow at top */ Cairo::RefPtr drop_shadow_pattern = Cairo::LinearGradient::create (0.0, 0.0, 0.0, 6 * scale); drop_shadow_pattern->add_color_stop_rgba (0, 0, 0, 0, 0.7); @@ -536,7 +538,7 @@ TriggerEntry::set_widget_colors (TriggerEntry::EnteredState es) //alternating darker bands if ((tref.slot / 2) % 2 == 0) { - bg_col = HSV (bg_col).darker (0.15).color (); + bg_col = HSV (bg_col).darker (0.25).color (); } set_fill_color (bg_col); diff --git a/libs/ardour/source.cc b/libs/ardour/source.cc index 6e7aba20aa..2b00ada40a 100644 --- a/libs/ardour/source.cc +++ b/libs/ardour/source.cc @@ -161,7 +161,6 @@ Source::set_state (const XMLNode& node, int version) const CueMarkers old_cues = _cue_markers; XMLNodeList nlist = node.children(); int64_t t; - samplepos_t ts; XMLNode* sd_node; if (node.name() == X_("Cues")) { @@ -189,14 +188,12 @@ Source::set_state (const XMLNode& node, int version) _timestamp = (time_t) t; } - if (node.get_property ("natural-position", ts)) { - _natural_position = timepos_t (ts); + if (node.get_property ("natural-position", _natural_position)) { _have_natural_position = true; - } else if (node.get_property ("timeline-position", ts)) { + } else if (node.get_property ("timeline-position", _natural_position)) { /* some older versions of ardour might have stored this with this property name. */ - _natural_position = timepos_t (ts); _have_natural_position = true; } diff --git a/libs/ardour/triggerbox.cc b/libs/ardour/triggerbox.cc index ca6076d4d4..185c9de16b 100644 --- a/libs/ardour/triggerbox.cc +++ b/libs/ardour/triggerbox.cc @@ -1257,8 +1257,13 @@ AudioTrigger::estimate_tempo () const double seconds = (double) data.length / _box.session().sample_rate(); const double quarters = (seconds / 60.) * _estimated_tempo; + + /* initialize bar count to match the file length ... user can later change this value */ _barcnt = quarters / _meter.divisions_per_bar(); + /* initialize our follow_length to match the barcnt ... user can later change this value */ + _follow_length = (Temporal::BBT_Offset( rint(_barcnt), 0, 0)); + /* now check the determined tempo and force it to a value that gives us an integer bar/quarter count. This is a heuristic that tries to avoid clips that slightly over- or underrun a quantization point, diff --git a/libs/canvas/arc.cc b/libs/canvas/arc.cc index 0ca1898586..0d8d014e4c 100644 --- a/libs/canvas/arc.cc +++ b/libs/canvas/arc.cc @@ -68,7 +68,7 @@ Arc::compute_bounding_box () const } void -Arc::render (Rect const & /*area*/, Cairo::RefPtr context) const +Arc::render (Rect const & area, Cairo::RefPtr context) const { if (_radius <= 0.0 || _arc_degrees <= 0.0 || (!fill() && !outline())) { return; @@ -91,6 +91,8 @@ Arc::render (Rect const & /*area*/, Cairo::RefPtr context) const setup_outline_context (context); context->stroke (); } + + render_children (area, context); } void diff --git a/libs/temporal/temporal/tempo.h b/libs/temporal/temporal/tempo.h index 1fd1363575..c62391bae8 100644 --- a/libs/temporal/temporal/tempo.h +++ b/libs/temporal/temporal/tempo.h @@ -869,6 +869,10 @@ class /*LIBTEMPORAL_API*/ TempoMap : public PBD::StatefulDestructible typedef boost::intrusive::list> MusicTimes; typedef boost::intrusive::list> Points; + Tempos const & tempos() const { return _tempos; } + Meters const & meters() const { return _meters; } + MusicTimes const & bartimes() const { return _bartimes; } + LIBTEMPORAL_API Beats quarters_at_sample (samplepos_t sc) const { return quarters_at_superclock (samples_to_superclock (sc, TEMPORAL_SAMPLE_RATE)); } LIBTEMPORAL_API Beats quarters_at_superclock (superclock_t sc) const;