X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Fautomation_time_axis.cc;h=369989334b2e71a5134a1d0ef52f2f82f375ce3c;hb=39f65bbce209e1be1591dd0a32c34ad6a11bcf97;hp=22f38c0545c76cce4c1031bed9cc8ce4d6f58f72;hpb=f6e182b937efda6ed0ba50dbc02af98524beb61c;p=ardour.git diff --git a/gtk2_ardour/automation_time_axis.cc b/gtk2_ardour/automation_time_axis.cc index 22f38c0545..369989334b 100644 --- a/gtk2_ardour/automation_time_axis.cc +++ b/gtk2_ardour/automation_time_axis.cc @@ -18,9 +18,11 @@ */ #include -#include + #include +#include + #include "pbd/error.h" #include "pbd/memento_command.h" #include "pbd/stacktrace.h" @@ -29,13 +31,15 @@ #include "pbd/unwind.h" #include "ardour/automation_control.h" -#include "ardour/beats_frames_converter.h" +#include "ardour/beats_samples_converter.h" #include "ardour/event_type_map.h" #include "ardour/parameter_types.h" #include "ardour/profile.h" #include "ardour/route.h" #include "ardour/session.h" +#include "gtkmm2ext/utils.h" + #include "canvas/debug.h" #include "widgets/tooltips.h" @@ -134,6 +138,7 @@ AutomationTimeAxisView::AutomationTimeAxisView ( auto_off_item = 0; auto_touch_item = 0; + auto_latch_item = 0; auto_write_item = 0; auto_play_item = 0; mode_discrete_item = 0; @@ -157,14 +162,17 @@ AutomationTimeAxisView::AutomationTimeAxisView ( using namespace Menu_Helpers; - auto_dropdown.AddMenuElem (MenuElem (S_("Automation|Manual"), sigc::bind (sigc::mem_fun(*this, + auto_dropdown.AddMenuElem (MenuElem (automation_state_off_string(), sigc::bind (sigc::mem_fun(*this, &AutomationTimeAxisView::set_automation_state), (AutoState) ARDOUR::Off))); auto_dropdown.AddMenuElem (MenuElem (_("Play"), sigc::bind (sigc::mem_fun(*this, &AutomationTimeAxisView::set_automation_state), (AutoState) Play))); - auto_dropdown.AddMenuElem (MenuElem (_("Write"), sigc::bind (sigc::mem_fun(*this, - &AutomationTimeAxisView::set_automation_state), (AutoState) Write))); - auto_dropdown.AddMenuElem (MenuElem (_("Touch"), sigc::bind (sigc::mem_fun(*this, - &AutomationTimeAxisView::set_automation_state), (AutoState) Touch))); + + if (!(_parameter.type() >= MidiCCAutomation && + _parameter.type() <= MidiChannelPressureAutomation)) { + auto_dropdown.AddMenuElem (MenuElem (_("Write"), sigc::bind (sigc::mem_fun(*this, &AutomationTimeAxisView::set_automation_state), (AutoState) Write))); + auto_dropdown.AddMenuElem (MenuElem (_("Touch"), sigc::bind (sigc::mem_fun(*this, &AutomationTimeAxisView::set_automation_state), (AutoState) Touch))); + auto_dropdown.AddMenuElem (MenuElem (_("Latch"), sigc::bind (sigc::mem_fun(*this, &AutomationTimeAxisView::set_automation_state), (AutoState) Latch))); + } /* XXX translators: use a string here that will be at least as long as the longest automation label (see ::automation_state_changed() @@ -309,13 +317,16 @@ AutomationTimeAxisView::AutomationTimeAxisView ( AutomationTimeAxisView::~AutomationTimeAxisView () { - cleanup_gui_properties (); + if (_stripable) { + cleanup_gui_properties (); + } delete _view; } void AutomationTimeAxisView::route_going_away () { + cleanup_gui_properties (); _stripable.reset (); } @@ -331,6 +342,7 @@ AutomationTimeAxisView::set_automation_state (AutoState state) } else if (_control) { _control->set_automation_state (state); + _session->set_dirty (); } if (_view) { @@ -359,50 +371,76 @@ AutomationTimeAxisView::automation_state_changed () state = ARDOUR::Off; } - switch (state & (ARDOUR::Off|Play|Touch|Write)) { + switch (state & (ARDOUR::Off|Play|Touch|Write|Latch)) { case ARDOUR::Off: - auto_dropdown.set_text (S_("Automation|Manual")); + auto_dropdown.set_text (automation_state_off_string()); + ignore_state_request = true; if (auto_off_item) { - ignore_state_request = true; auto_off_item->set_active (true); auto_play_item->set_active (false); + } + if (auto_touch_item) { auto_touch_item->set_active (false); + auto_latch_item->set_active (false); auto_write_item->set_active (false); - ignore_state_request = false; } + ignore_state_request = false; break; case Play: auto_dropdown.set_text (_("Play")); - if (auto_play_item) { - ignore_state_request = true; + ignore_state_request = true; + if (auto_off_item) { auto_play_item->set_active (true); auto_off_item->set_active (false); + } + if (auto_touch_item) { auto_touch_item->set_active (false); + auto_latch_item->set_active (false); auto_write_item->set_active (false); - ignore_state_request = false; } + ignore_state_request = false; break; case Write: auto_dropdown.set_text (_("Write")); - if (auto_write_item) { - ignore_state_request = true; - auto_write_item->set_active (true); + ignore_state_request = true; + if (auto_off_item) { auto_off_item->set_active (false); auto_play_item->set_active (false); + } + if (auto_touch_item) { + auto_write_item->set_active (true); auto_touch_item->set_active (false); - ignore_state_request = false; + auto_latch_item->set_active (false); } + ignore_state_request = false; break; case Touch: auto_dropdown.set_text (_("Touch")); + ignore_state_request = true; + if (auto_off_item) { + auto_off_item->set_active (false); + auto_play_item->set_active (false); + } if (auto_touch_item) { - ignore_state_request = true; auto_touch_item->set_active (true); + auto_write_item->set_active (false); + auto_latch_item->set_active (false); + } + ignore_state_request = false; + break; + case Latch: + auto_dropdown.set_text (_("Latch")); + ignore_state_request = true; + if (auto_off_item) { auto_off_item->set_active (false); auto_play_item->set_active (false); + } + if (auto_touch_item) { + auto_latch_item->set_active (true); + auto_touch_item->set_active (false); auto_write_item->set_active (false); - ignore_state_request = false; } + ignore_state_request = false; break; default: auto_dropdown.set_text (_("???")); @@ -472,7 +510,9 @@ AutomationTimeAxisView::clear_clicked () } else if (_view) { _view->clear (); } - set_automation_state ((AutoState) ARDOUR::Off); + if (!EventTypeMap::instance().type_is_midi (_control->parameter().type())) { + set_automation_state ((AutoState) ARDOUR::Off); + } _editor.commit_reversible_command (); _session->set_dirty (); } @@ -502,10 +542,7 @@ AutomationTimeAxisView::set_height (uint32_t h, TrackHeightMode m) first_call_to_set_height = false; if (h >= preset_height (HeightNormal)) { - if (!(_parameter.type() >= MidiCCAutomation && - _parameter.type() <= MidiChannelPressureAutomation)) { - auto_dropdown.show(); - } + auto_dropdown.show(); name_label.show(); hide_button.show(); @@ -543,13 +580,23 @@ AutomationTimeAxisView::hide_clicked () { hide_button.set_sensitive(false); set_marked_for_display (false); - RouteTimeAxisView* rtv = dynamic_cast(parent); - if (rtv) { - rtv->request_redraw (); + StripableTimeAxisView* stv = dynamic_cast(parent); + if (stv) { + stv->request_redraw (); } hide_button.set_sensitive(true); } +string +AutomationTimeAxisView::automation_state_off_string () const +{ + if (_parameter.type() >= MidiCCAutomation && _parameter.type() <= MidiChannelPressureAutomation) { + return S_("Automation|Off"); + } + + return S_("Automation|Manual"); +} + void AutomationTimeAxisView::build_display_menu () { @@ -574,7 +621,7 @@ AutomationTimeAxisView::build_display_menu () auto_state_menu->set_name ("ArdourContextMenu"); MenuList& as_items = auto_state_menu->items(); - as_items.push_back (CheckMenuElem (S_("Automation|Manual"), sigc::bind ( + as_items.push_back (CheckMenuElem (automation_state_off_string(), sigc::bind ( sigc::mem_fun(*this, &AutomationTimeAxisView::set_automation_state), (AutoState) ARDOUR::Off))); auto_off_item = dynamic_cast(&as_items.back()); @@ -584,21 +631,26 @@ AutomationTimeAxisView::build_display_menu () (AutoState) Play))); auto_play_item = dynamic_cast(&as_items.back()); - as_items.push_back (CheckMenuElem (_("Write"), sigc::bind ( - sigc::mem_fun(*this, &AutomationTimeAxisView::set_automation_state), - (AutoState) Write))); - auto_write_item = dynamic_cast(&as_items.back()); + if (!(_parameter.type() >= MidiCCAutomation && + _parameter.type() <= MidiChannelPressureAutomation)) { + as_items.push_back (CheckMenuElem (_("Write"), sigc::bind ( + sigc::mem_fun(*this, &AutomationTimeAxisView::set_automation_state), + (AutoState) Write))); + auto_write_item = dynamic_cast(&as_items.back()); - as_items.push_back (CheckMenuElem (_("Touch"), sigc::bind ( - sigc::mem_fun(*this, &AutomationTimeAxisView::set_automation_state), + as_items.push_back (CheckMenuElem (_("Touch"), sigc::bind ( + sigc::mem_fun(*this, &AutomationTimeAxisView::set_automation_state), (AutoState) Touch))); - auto_touch_item = dynamic_cast(&as_items.back()); + auto_touch_item = dynamic_cast(&as_items.back()); - if (!(_parameter.type() >= MidiCCAutomation && - _parameter.type() <= MidiChannelPressureAutomation)) { - items.push_back (MenuElem (_("State"), *auto_state_menu)); + as_items.push_back (CheckMenuElem (_("Latch"), sigc::bind ( + sigc::mem_fun(*this, &AutomationTimeAxisView::set_automation_state), + (AutoState) Latch))); + auto_latch_item = dynamic_cast(&as_items.back()); } + items.push_back (MenuElem (_("State"), *auto_state_menu)); + /* mode menu */ /* current interpolation state */ @@ -625,7 +677,7 @@ AutomationTimeAxisView::build_display_menu () items.push_back (MenuElem (_("Mode"), *auto_mode_menu)); } else { -#ifdef XXX_NEW_INTERPOLATON__BREAK_SESSION_FORMAT_XXX + Menu* auto_mode_menu = manage (new Menu); auto_mode_menu->set_name ("ArdourContextMenu"); MenuList& am_items = auto_mode_menu->items(); @@ -665,7 +717,6 @@ AutomationTimeAxisView::build_display_menu () delete auto_mode_menu; auto_mode_menu = 0; } -#endif } /* make sure the automation menu state is correct */ @@ -675,7 +726,7 @@ AutomationTimeAxisView::build_display_menu () } void -AutomationTimeAxisView::add_automation_event (GdkEvent* event, framepos_t frame, double y, bool with_guard_points) +AutomationTimeAxisView::add_automation_event (GdkEvent* event, samplepos_t sample, double y, bool with_guard_points) { if (!_line) { return; @@ -690,14 +741,14 @@ AutomationTimeAxisView::add_automation_event (GdkEvent* event, framepos_t frame, return; } - MusicFrame when (frame, 0); + MusicSample when (sample, 0); _editor.snap_to_with_modifier (when, event); if (UIConfiguration::instance().get_new_automation_points_on_lane()) { if (_control->list()->size () == 0) { y = _control->get_value (); } else { - y = _control->list()->eval (when.frame); + y = _control->list()->eval (when.sample); } } else { double x = 0; @@ -711,12 +762,12 @@ AutomationTimeAxisView::add_automation_event (GdkEvent* event, framepos_t frame, XMLNode& before = list->get_state(); std::list results; - if (list->editor_add (when.frame, y, with_guard_points)) { + if (list->editor_add (when.sample, y, with_guard_points)) { XMLNode& after = list->get_state(); _editor.begin_reversible_command (_("add automation event")); _session->add_command (new MementoCommand (*list.get (), &before, &after)); - _line->get_selectables (when.frame, when.frame, 0.0, 1.0, results); + _line->get_selectables (when.sample, when.sample, 0.0, 1.0, results); _editor.get_selection ().set (results); _editor.commit_reversible_command (); @@ -725,7 +776,7 @@ AutomationTimeAxisView::add_automation_event (GdkEvent* event, framepos_t frame, } bool -AutomationTimeAxisView::paste (framepos_t pos, const Selection& selection, PasteContext& ctx, const int32_t divisions) +AutomationTimeAxisView::paste (samplepos_t pos, const Selection& selection, PasteContext& ctx, const int32_t divisions) { if (_line) { return paste_one (pos, ctx.count, ctx.times, selection, ctx.counts, ctx.greedy); @@ -746,7 +797,7 @@ AutomationTimeAxisView::paste (framepos_t pos, const Selection& selection, Paste } bool -AutomationTimeAxisView::paste_one (framepos_t pos, unsigned paste_count, float times, const Selection& selection, ItemCounts& counts, bool greedy) +AutomationTimeAxisView::paste_one (samplepos_t pos, unsigned paste_count, float times, const Selection& selection, ItemCounts& counts, bool greedy) { boost::shared_ptr alist(_line->the_list()); @@ -773,7 +824,7 @@ AutomationTimeAxisView::paste_one (framepos_t pos, unsigned paste_count, float t if (parameter_is_midi (src_type)) { // convert length to samples (incl tempo-ramps) - len = DoubleBeatsFramesConverter (_session->tempo_map(), pos).to (len * paste_count); + len = DoubleBeatsSamplesConverter (_session->tempo_map(), pos).to (len * paste_count); pos += _editor.get_paste_offset (pos, paste_count > 0 ? 1 : 0, len); } else { pos += _editor.get_paste_offset (pos, paste_count, len); @@ -783,14 +834,14 @@ AutomationTimeAxisView::paste_one (framepos_t pos, unsigned paste_count, float t double const model_pos = _line->time_converter().from (pos - _line->time_converter().origin_b ()); XMLNode &before = alist->get_state(); - alist->paste (**p, model_pos, DoubleBeatsFramesConverter (_session->tempo_map(), pos)); + alist->paste (**p, model_pos, DoubleBeatsSamplesConverter (_session->tempo_map(), pos)); _session->add_command (new MementoCommand(*alist.get(), &before, &alist->get_state())); return true; } void -AutomationTimeAxisView::get_selectables (framepos_t start, framepos_t end, double top, double bot, list& results, bool /*within*/) +AutomationTimeAxisView::get_selectables (samplepos_t start, samplepos_t end, double top, double bot, list& results, bool /*within*/) { if (!_line && !_view) { return; @@ -884,6 +935,19 @@ AutomationTimeAxisView::add_line (boost::shared_ptr line) line->add_visibility (AutomationLine::Line); } +bool +AutomationTimeAxisView::propagate_time_selection () const +{ + /* MIDI automation is part of the MIDI region. It is always + * implicily selected with the parent, regardless of TAV selection + */ + if (_parameter.type() >= MidiCCAutomation && + _parameter.type() <= MidiChannelPressureAutomation) { + return true; + } + return false; +} + void AutomationTimeAxisView::entered() { @@ -1074,7 +1138,7 @@ AutomationTimeAxisView::cut_copy_clear_one (AutomationLine& line, Selection& sel XMLNode &before = alist->get_state(); /* convert time selection to automation list model coordinates */ - const Evoral::TimeConverter& tc = line.time_converter (); + const Evoral::TimeConverter& tc = line.time_converter (); double const start = tc.from (selection.time.front().start - tc.origin_b ()); double const end = tc.from (selection.time.front().end - tc.origin_b ()); @@ -1133,4 +1197,3 @@ AutomationTimeAxisView::color () const { return gdk_color_from_rgb (_stripable->presentation_info().color()); } -