diff --git a/gtk2_ardour/ardour3_ui_dark.rc.in b/gtk2_ardour/ardour3_ui_dark.rc.in index 1be6acbb9d..dc560699d0 100644 --- a/gtk2_ardour/ardour3_ui_dark.rc.in +++ b/gtk2_ardour/ardour3_ui_dark.rc.in @@ -303,6 +303,19 @@ style "track_rec_enable_button_alternate" = "small_button" bg[PRELIGHT] = { 0.91, 0.68, 0.68} } +style "track_rec_enable_button_alternate_two" = "small_button" +{ + fg[SELECTED] = { 0.0, 0.0, 0.0 } + fg[ACTIVE] = { 0.0, 0.0, 0.0 } + fg[PRELIGHT] = { 0.0, 0.0, 0.0 } + fg[NORMAL] = { 0.0, 0.0, 0.0 } + + bg[NORMAL] = { 0.91, 0.68, 0.00 } + bg[ACTIVE] = { 0.91, 0.68, 0.00 } + bg[SELECTED] = { 0.91, 0.68, 0.00 } + bg[PRELIGHT] = { 0.91, 0.68, 0.00 } +} + style "mixer_track_rec_enable_button" = "track_rec_enable_button" { font_name = "@FONT_SMALLER@" @@ -564,6 +577,19 @@ style "transport_button_active" fg[ACTIVE] = { 0, 0, 0 } } +style "transport_button_alternate_two" +{ + fg[SELECTED] = { 0.0, 0.0, 0.0 } + fg[ACTIVE] = { 0.0, 0.0, 0.0 } + fg[PRELIGHT] = { 0.0, 0.0, 0.0 } + fg[NORMAL] = { 0.0, 0.0, 0.0 } + + bg[NORMAL] = { 0.91, 0.68, 0.00 } + bg[ACTIVE] = { 0.91, 0.68, 0.00 } + bg[SELECTED] = { 0.91, 0.68, 0.00 } + bg[PRELIGHT] = { 0.91, 0.68, 0.00 } +} + style "transport_rec_button" { @@ -1479,6 +1505,7 @@ widget "*NewSessionDialogButton" style:highest "small_red_active_and_selected_bu widget "*RecordEnableButton" style:highest "track_rec_enable_button" widget "*RecordEnableButton-active" style:highest "track_rec_enable_button_active" widget "*RecordEnableButton-alternate" style:highest "track_rec_enable_button_alternate" +widget "*RecordEnableButton-alternate2" style:highest "track_rec_enable_button_alternate_two" widget "*MixerRecordEnableButton" style:highest "mixer_track_rec_enable_button" widget "*MixerRecordEnableButton-active" style:highest "mixer_track_rec_enable_button_active" widget "*MixerRecordEnableButton-alternate" style:highest "mixer_track_rec_enable_button_alternate" @@ -1518,6 +1545,7 @@ widget "*EditGroupButton" style:highest "very_small_button" widget "*EditGroupButtonLabel" style:highest "very_small_button" widget "*TransportButton" style:highest "transport_button" widget "*TransportButton-active" style:highest "transport_button_active" +widget "*TransportButton-alternate2" style:highest "transport_button_alternate_two" widget "*TransportSyncButton" style:highest "transport_button" widget "*TransportSyncButton*" style:highest "transport_button" widget "*TransportSyncButton-active" style:highest "sync_alert" diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc index 9cc879c3ff..9d789c20be 100644 --- a/gtk2_ardour/ardour_ui.cc +++ b/gtk2_ardour/ardour_ui.cc @@ -1690,7 +1690,7 @@ ARDOUR_UI::transport_forward (int option) } void -ARDOUR_UI::toggle_record_enable (uint32_t dstream) +ARDOUR_UI::toggle_record_enable (uint32_t rid) { if (_session == 0) { return; @@ -1698,12 +1698,12 @@ ARDOUR_UI::toggle_record_enable (uint32_t dstream) boost::shared_ptr r; - if ((r = _session->route_by_remote_id (dstream)) != 0) { + if ((r = _session->route_by_remote_id (rid)) != 0) { Track* t; if ((t = dynamic_cast(r.get())) != 0) { - t->set_record_enabled (!t->record_enabled()); + t->set_record_enabled (!t->record_enabled(), this); } } if (_session == 0) { @@ -2103,6 +2103,10 @@ ARDOUR_UI::transport_rec_enable_blink (bool onoff) return; } + if (_session->step_editing()) { + return; + } + Session::RecordState const r = _session->record_status (); bool const h = _session->have_rec_enabled_track (); @@ -3348,6 +3352,22 @@ ARDOUR_UI::update_transport_clocks (nframes_t pos) } } + +void +ARDOUR_UI::step_edit_status_change (bool yn) +{ + // XXX should really store pre-step edit status of things + // we make insensitive + + if (yn) { + rec_button.set_visual_state (3); + rec_button.set_sensitive (false); + } else { + rec_button.set_visual_state (0); + rec_button.set_sensitive (true); + } +} + void ARDOUR_UI::record_state_changed () { diff --git a/gtk2_ardour/ardour_ui.h b/gtk2_ardour/ardour_ui.h index 4e8137d76e..04cd080ac3 100644 --- a/gtk2_ardour/ardour_ui.h +++ b/gtk2_ardour/ardour_ui.h @@ -697,6 +697,8 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr void fontconfig_dialog (); PBD::ScopedConnectionList forever_connections; + + void step_edit_status_change (bool); }; #endif /* __ardour_gui_h__ */ diff --git a/gtk2_ardour/ardour_ui_dialogs.cc b/gtk2_ardour/ardour_ui_dialogs.cc index c187a5df56..747354ca4e 100644 --- a/gtk2_ardour/ardour_ui_dialogs.cc +++ b/gtk2_ardour/ardour_ui_dialogs.cc @@ -126,6 +126,7 @@ ARDOUR_UI::set_session (Session *s) Blink.connect (sigc::mem_fun(*this, &ARDOUR_UI::audition_blink)); _session->RecordStateChanged.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::record_state_changed, this), gui_context()); + _session->StepEditStatusChange.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::step_edit_status_change, this, _1), gui_context()); _session->TransportStateChange.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::map_transport_state, this), gui_context()); _session->DirtyChanged.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::update_autosave, this), gui_context()); diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc index 49470849c6..7f19e1e415 100644 --- a/gtk2_ardour/editor.cc +++ b/gtk2_ardour/editor.cc @@ -1102,6 +1102,7 @@ Editor::set_session (Session *t) but use Gtkmm2ext::UI::instance()->call_slot(); */ + _session->StepEditStatusChange.connect (_session_connections, invalidator (*this), ui_bind(&Editor::step_edit_status_change, this, _1), gui_context()); _session->TransportStateChange.connect (_session_connections, invalidator (*this), boost::bind (&Editor::map_transport_state, this), gui_context()); _session->PositionChanged.connect (_session_connections, invalidator (*this), ui_bind (&Editor::map_position_change, this, _1), gui_context()); _session->RouteAdded.connect (_session_connections, invalidator (*this), ui_bind (&Editor::handle_new_route, this, _1), gui_context()); @@ -5188,6 +5189,16 @@ Editor::show_region_in_region_list () _regions->selection_mapover (sigc::mem_fun (*this, &Editor::show_a_region)); } +void +Editor::step_edit_status_change (bool yn) +{ + if (yn) { + start_step_editing (); + } else { + stop_step_editing (); + } +} + void Editor::start_step_editing () { @@ -5480,3 +5491,4 @@ Editor::show_editor_list (bool yn) the_notebook.hide(); } } + diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index 167872fcdd..15758b97fb 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -2037,6 +2037,7 @@ public: EditorGroupTabs* _group_tabs; void fit_route_group (ARDOUR::RouteGroup *); + void step_edit_status_change (bool); void start_step_editing (); void stop_step_editing (); bool check_step_edit (); diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc index 0302054760..da2ee66a0f 100644 --- a/gtk2_ardour/editor_mouse.cc +++ b/gtk2_ardour/editor_mouse.cc @@ -2659,37 +2659,19 @@ Editor::set_internal_edit (bool yn) mouse_select_button.set_image (*(manage (new Image (::get_icon("midi_tool_pencil"))))); mouse_select_button.get_image ()->show (); ARDOUR_UI::instance()->tooltips().set_tip (mouse_select_button, _("Draw/Edit MIDI Notes")); - - for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { - MidiTimeAxisView* mtv = dynamic_cast (*i); - if (mtv) { - mtv->start_step_editing (); - } - } + set_canvas_cursor (); /* deselect everything to avoid confusion when e.g. we can't now cut a previously selected region because cut means "cut note" rather than "cut region". */ selection->clear (); - start_step_editing (); - set_canvas_cursor (); - } else { mouse_select_button.set_image (*(manage (new Image (::get_icon("tool_range"))))); mouse_select_button.get_image ()->show (); ARDOUR_UI::instance()->tooltips().set_tip (mouse_select_button, _("Select/Move Ranges")); - stop_step_editing (); - - for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { - MidiTimeAxisView* mtv = dynamic_cast (*i); - if (mtv) { - mtv->stop_step_editing (); - } - } - - mouse_mode_toggled (mouse_mode); + mouse_mode_toggled (mouse_mode); // sets cursor } } diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc index adc9078fba..cb76fcb1ec 100644 --- a/gtk2_ardour/editor_ops.cc +++ b/gtk2_ardour/editor_ops.cc @@ -5116,7 +5116,7 @@ Editor::toggle_record_enable () first = false; } - rtav->track()->set_record_enable(new_state, this); + rtav->track()->set_record_enabled (new_state, this); } } diff --git a/gtk2_ardour/editor_routes.cc b/gtk2_ardour/editor_routes.cc index 308f0c50b8..81e56c3e32 100644 --- a/gtk2_ardour/editor_routes.cc +++ b/gtk2_ardour/editor_routes.cc @@ -222,7 +222,7 @@ EditorRoutes::on_tv_rec_enable_toggled (Glib::ustring const & path_string) if (atv != 0 && atv->is_audio_track()){ boost::shared_ptr rl (new RouteList); rl->push_back (atv->route()); - _session->set_record_enable (rl, !atv->track()->record_enabled(), Session::rt_cleanup); + _session->set_record_enabled (rl, !atv->track()->record_enabled(), Session::rt_cleanup); } } diff --git a/gtk2_ardour/midi_time_axis.cc b/gtk2_ardour/midi_time_axis.cc index a4e09871c9..cb4eb795bd 100644 --- a/gtk2_ardour/midi_time_axis.cc +++ b/gtk2_ardour/midi_time_axis.cc @@ -858,6 +858,20 @@ MidiTimeAxisView::route_active_changed () } } +void +MidiTimeAxisView::toggle_step_edit () +{ + if (_route->record_enabled()) { + return; + } + + if (midi_track()->step_editing ()) { + stop_step_editing (); + } else { + start_step_editing (); + } +} + void MidiTimeAxisView::start_step_editing () { @@ -918,6 +932,8 @@ MidiTimeAxisView::check_step_edit () fatal << X_("programming error: no view found for new MIDI region") << endmsg; /*NOTREACHED*/ } + cerr << "New step edit region is called " << step_edit_region->name() + << " view @ " << step_edit_region_view << endl; } if (step_edit_region_view) { @@ -946,7 +962,7 @@ MidiTimeAxisView::step_edit_rest () } boost::shared_ptr -MidiTimeAxisView::add_region (nframes64_t pos) +MidiTimeAxisView::add_region (framepos_t pos) { Editor* real_editor = dynamic_cast (&_editor); diff --git a/gtk2_ardour/midi_time_axis.h b/gtk2_ardour/midi_time_axis.h index e15167f855..b118b9ab63 100644 --- a/gtk2_ardour/midi_time_axis.h +++ b/gtk2_ardour/midi_time_axis.h @@ -67,7 +67,7 @@ class MidiTimeAxisView : public RouteTimeAxisView void set_height (uint32_t); void hide (); - boost::shared_ptr add_region (nframes64_t pos); + boost::shared_ptr add_region (ARDOUR::framepos_t pos); void show_all_automation (); void show_existing_automation (); @@ -86,6 +86,7 @@ class MidiTimeAxisView : public RouteTimeAxisView return _midi_patch_settings_changed; } + void toggle_step_edit (); void start_step_editing (); void stop_step_editing (); void check_step_edit (); diff --git a/gtk2_ardour/route_time_axis.cc b/gtk2_ardour/route_time_axis.cc index 49c49a3734..d1df63d187 100644 --- a/gtk2_ardour/route_time_axis.cc +++ b/gtk2_ardour/route_time_axis.cc @@ -170,7 +170,12 @@ RouteTimeAxisView::RouteTimeAxisView (PublicEditor& ed, Session* sess, boost::sh rec_enable_button->show_all (); controls_table.attach (*rec_enable_button, 5, 6, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 0, 0); - ARDOUR_UI::instance()->set_tip(*rec_enable_button, _("Record")); + + if (is_midi_track()) { + ARDOUR_UI::instance()->set_tip(*rec_enable_button, _("Record (Right-click for Step Edit)")); + } else { + ARDOUR_UI::instance()->set_tip(*rec_enable_button, _("Record")); + } rec_enable_button->set_sensitive (_session->writable()); } diff --git a/gtk2_ardour/route_ui.cc b/gtk2_ardour/route_ui.cc index 71d38360d5..6e9f5a73d1 100644 --- a/gtk2_ardour/route_ui.cc +++ b/gtk2_ardour/route_ui.cc @@ -83,6 +83,7 @@ RouteUI::~RouteUI() delete solo_menu; delete mute_menu; delete sends_menu; + delete record_menu; } void @@ -93,6 +94,7 @@ RouteUI::init () mute_menu = 0; solo_menu = 0; sends_menu = 0; + record_menu = 0; pre_fader_mute_check = 0; post_fader_mute_check = 0; listen_mute_check = 0; @@ -106,6 +108,7 @@ RouteUI::init () _mute_release = 0; route_active_menu_item = 0; denormal_menu_item = 0; + step_edit_item = 0; multiple_mute_change = false; multiple_solo_change = false; @@ -229,6 +232,12 @@ RouteUI::set_route (boost::shared_ptr rp) rec_enable_button->set_controllable (t->rec_enable_control()); update_rec_display (); + + if (is_midi_track()) { + midi_track()->StepEditStatusChange.connect (route_connections, invalidator (*this), + ui_bind (&RouteUI::step_edit_changed, this, _1), gui_context()); + } + } mute_button->unset_flags (Gtk::CAN_FOCUS); @@ -526,6 +535,15 @@ RouteUI::rec_enable_press(GdkEventButton* ev) return true; } + if (is_midi_track()) { + + /* cannot rec-enable while step-editing */ + + if (midi_track()->step_editing()) { + return true; + } + } + if (!ignore_toggle && is_track() && rec_enable_button) { if (Keyboard::is_button2_event (ev)) { @@ -535,7 +553,7 @@ RouteUI::rec_enable_press(GdkEventButton* ev) } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) { - _session->set_record_enable (_session->get_routes(), !rec_enable_button->get_active()); + _session->set_record_enabled (_session->get_routes(), !rec_enable_button->get_active()); } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) { @@ -543,7 +561,7 @@ RouteUI::rec_enable_press(GdkEventButton* ev) NOTE: Primary-button2 is MIDI learn. */ if (ev->button == 1 && _route->route_group()) { - _session->set_record_enable (_route->route_group()->route_list(), !rec_enable_button->get_active(), Session::rt_cleanup, true); + _session->set_record_enabled (_route->route_group()->route_list(), !rec_enable_button->get_active(), Session::rt_cleanup, true); } } else if (Keyboard::is_context_menu_event (ev)) { @@ -554,16 +572,67 @@ RouteUI::rec_enable_press(GdkEventButton* ev) boost::shared_ptr rl (new RouteList); rl->push_back (route()); - _session->set_record_enable (rl, !rec_enable_button->get_active()); + _session->set_record_enabled (rl, !rec_enable_button->get_active()); } } return true; } -bool -RouteUI::rec_enable_release (GdkEventButton*) +void +RouteUI::build_record_menu () { + if (record_menu) { + return; + } + + /* no rec-button context menu for non-MIDI tracks + */ + + if (!is_midi_track()) { + return; + } + + record_menu = new Menu; + record_menu->set_name ("ArdourContextMenu"); + + using namespace Menu_Helpers; + MenuList& items = record_menu->items(); + + items.push_back (CheckMenuElem (_("Step Edit"), sigc::mem_fun (*this, &RouteUI::toggle_step_edit))); + step_edit_item = dynamic_cast (&items.back()); +} + +void +RouteUI::toggle_step_edit () +{ +} + +void +RouteUI::step_edit_changed (bool yn) +{ + if (yn) { + if (rec_enable_button) { + rec_enable_button->set_visual_state (3); + } + } else { + if (rec_enable_button) { + rec_enable_button->set_visual_state (0); + } + } +} + +bool +RouteUI::rec_enable_release (GdkEventButton* ev) +{ + if (Keyboard::is_context_menu_event (ev)) { + build_record_menu (); + if (record_menu) { + record_menu->popup (1, ev->time); + } + return true; + } + return true; } @@ -907,7 +976,7 @@ RouteUI::update_mute_display () void RouteUI::route_rec_enable_changed () { - Gtkmm2ext::UI::instance()->call_slot (invalidator (*this), boost::bind (&RouteUI::update_rec_display, this)); + update_rec_display (); } void @@ -939,18 +1008,17 @@ RouteUI::update_rec_display () /* now make sure its color state is correct */ if (model) { - - switch (_session->record_status ()) { - case Session::Recording: - rec_enable_button->set_visual_state (1); - break; - - case Session::Disabled: - case Session::Enabled: - rec_enable_button->set_visual_state (2); - break; - - } + switch (_session->record_status ()) { + case Session::Recording: + rec_enable_button->set_visual_state (1); + break; + + case Session::Disabled: + case Session::Enabled: + rec_enable_button->set_visual_state (2); + break; + + } } else { rec_enable_button->set_visual_state (0); diff --git a/gtk2_ardour/route_ui.h b/gtk2_ardour/route_ui.h index cc11b18094..8d819de505 100644 --- a/gtk2_ardour/route_ui.h +++ b/gtk2_ardour/route_ui.h @@ -180,6 +180,13 @@ class RouteUI : public virtual AxisView void toggle_route_active (); virtual void route_active_changed (); + Gtk::Menu* record_menu; + void build_record_menu (); + + Gtk::CheckMenuItem *step_edit_item; + virtual void toggle_step_edit (); + virtual void step_edit_changed (bool); + virtual void polarity_changed (); Gtk::CheckMenuItem *denormal_menu_item; diff --git a/libs/ardour/ardour/midi_track.h b/libs/ardour/ardour/midi_track.h index 42446da70d..df1d2e11df 100644 --- a/libs/ardour/ardour/midi_track.h +++ b/libs/ardour/ardour/midi_track.h @@ -46,6 +46,7 @@ public: void use_new_diskstream (); void set_diskstream (boost::shared_ptr); + void set_record_enabled (bool yn, void *src); void set_latency_delay (nframes_t); @@ -83,6 +84,8 @@ public: void set_step_editing (bool yn); MidiRingBuffer& step_edit_ring_buffer() { return _step_edit_ring_buffer; } + static PBD::Signal1 StepEditStatusChange; + uint8_t default_channel() const { return _default_channel; } void set_default_channel (uint8_t chn); @@ -94,7 +97,7 @@ public: ChannelMode get_channel_mode (); uint16_t get_channel_mask (); boost::shared_ptr midi_playlist (); - + protected: XMLNode& state (bool full); diff --git a/libs/ardour/ardour/public_diskstream.h b/libs/ardour/ardour/public_diskstream.h index a33c43f0cd..5c2c6d9fc6 100755 --- a/libs/ardour/ardour/public_diskstream.h +++ b/libs/ardour/ardour/public_diskstream.h @@ -65,7 +65,6 @@ public: virtual ChanCount n_channels () = 0; virtual nframes_t get_capture_start_frame (uint32_t n = 0) = 0; virtual AlignStyle alignment_style () const = 0; - virtual void set_record_enabled (bool) = 0; virtual nframes_t current_capture_start () const = 0; virtual nframes_t current_capture_end () const = 0; virtual void playlist_modified () = 0; diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h index 7692583feb..54eb41f97b 100644 --- a/libs/ardour/ardour/route.h +++ b/libs/ardour/ardour/route.h @@ -112,7 +112,7 @@ class Route : public SessionObject, public Automatable, public RouteGroupMember, virtual void toggle_monitor_input (); virtual bool can_record() { return false; } - virtual void set_record_enable (bool /*yn*/, void * /*src*/) {} + virtual void set_record_enabled (bool /*yn*/, void * /*src*/) {} virtual bool record_enabled() const { return false; } virtual void handle_transport_stopped (bool abort, bool did_locate, bool flush_processors); virtual void set_pending_declick (int); diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index 18ef620a89..4627204888 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -282,6 +282,9 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi /** Emitted when anything about any of our route groups changes */ PBD::Signal0 RouteGroupChanged; + /* Step Editing status changed */ + PBD::Signal1 StepEditStatusChange; + void queue_event (SessionEvent*); void request_roll_at_and_return (nframes_t start, nframes_t return_to); @@ -591,7 +594,7 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi void set_just_one_solo (boost::shared_ptr, bool, SessionEvent::RTeventCallback after = rt_cleanup); void set_mute (boost::shared_ptr, bool, SessionEvent::RTeventCallback after = rt_cleanup, bool group_override = false); void set_listen (boost::shared_ptr, bool, SessionEvent::RTeventCallback after = rt_cleanup, bool group_override = false); - void set_record_enable (boost::shared_ptr, bool, SessionEvent::RTeventCallback after = rt_cleanup, bool group_override = false); + void set_record_enabled (boost::shared_ptr, bool, SessionEvent::RTeventCallback after = rt_cleanup, bool group_override = false); void set_solo_isolated (boost::shared_ptr, bool, SessionEvent::RTeventCallback after = rt_cleanup, bool group_override = false); PBD::Signal1 SoloActive; @@ -776,6 +779,8 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi PBD::Signal0 RouteOrderKeyChanged; + bool step_editing() const { return (_step_editors > 0); } + protected: friend class AudioEngine; void set_block_size (nframes_t nframes); @@ -1409,7 +1414,7 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi void rt_set_mute (boost::shared_ptr, bool yn, bool group_override); void rt_set_listen (boost::shared_ptr, bool yn, bool group_override); void rt_set_solo_isolated (boost::shared_ptr, bool yn, bool group_override); - void rt_set_record_enable (boost::shared_ptr, bool yn, bool group_override); + void rt_set_record_enabled (boost::shared_ptr, bool yn, bool group_override); /** temporary list of Diskstreams used only during load of 2.X sessions */ std::list > _diskstreams_2X; @@ -1420,6 +1425,9 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi void cleanup_stubfiles (); void route_order_key_changed (); + + void step_edit_status_change (bool); + uint32_t _step_editors; }; } // namespace ARDOUR diff --git a/libs/ardour/ardour/track.h b/libs/ardour/ardour/track.h index 60e628af79..b3d69e4403 100644 --- a/libs/ardour/ardour/track.h +++ b/libs/ardour/ardour/track.h @@ -90,7 +90,7 @@ class Track : public Route, public PublicDiskstream boost::shared_ptr rec_enable_control() { return _rec_enable_control; } bool record_enabled() const; - void set_record_enable (bool yn, void *src); + void set_record_enabled (bool yn, void *src); /* XXX: unfortunate that this is exposed */ PBD::ID const & diskstream_id () const; @@ -132,7 +132,6 @@ class Track : public Route, public PublicDiskstream ChanCount n_channels (); nframes_t get_capture_start_frame (uint32_t n = 0); AlignStyle alignment_style () const; - void set_record_enabled (bool); nframes_t current_capture_start () const; nframes_t current_capture_end () const; void playlist_modified (); diff --git a/libs/ardour/midi_track.cc b/libs/ardour/midi_track.cc index 3c43266219..9dced1e0b9 100644 --- a/libs/ardour/midi_track.cc +++ b/libs/ardour/midi_track.cc @@ -49,6 +49,8 @@ using namespace std; using namespace ARDOUR; using namespace PBD; +PBD::Signal1 MidiTrack::StepEditStatusChange; + MidiTrack::MidiTrack (Session& sess, string name, Route::Flag flag, TrackMode mode) : Track (sess, name, flag, mode, DataType::MIDI) , _immediate_events(1024) // FIXME: size? @@ -84,6 +86,16 @@ MidiTrack::use_new_diskstream () set_diskstream (ds); } +void +MidiTrack::set_record_enabled (bool yn, void *src) +{ + if (_step_editing) { + return; + } + + Track::set_record_enabled (yn, src); +} + void MidiTrack::set_diskstream (boost::shared_ptr ds) { @@ -376,7 +388,7 @@ MidiTrack::no_roll (nframes_t nframes, sframes_t start_frame, sframes_t end_fram { int ret = Track::no_roll (nframes, start_frame, end_frame, state_changing, can_record, rec_monitors_input); - if (ret == 0 && _diskstream->record_enabled() && _step_editing) { + if (ret == 0 && _step_editing) { push_midi_input_to_step_edit_ringbuffer (nframes); } @@ -570,8 +582,14 @@ MidiTrack::MidiControl::set_value(float val) void MidiTrack::set_step_editing (bool yn) { - cerr << name() << " IS NOW STEP EDITING\n"; - _step_editing = yn; + if (_session.record_status() != Session::Disabled) { + return; + } + + if (yn != _step_editing) { + _step_editing = yn; + StepEditStatusChange (yn); + } } void diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index 45de1db1f5..71277fa3cf 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -1041,6 +1041,10 @@ Session::step_back_from_record () void Session::maybe_enable_record () { + if (_step_editors > 0) { + return; + } + g_atomic_int_set (&_record_status, Enabled); /* this function is currently called from somewhere other than an RT thread. @@ -1926,6 +1930,11 @@ Session::add_routes (RouteList& new_routes, bool save) tr->PlaylistChanged.connect_same_thread (*this, boost::bind (&Session::track_playlist_changed, this, boost::weak_ptr (tr))); track_playlist_changed (boost::weak_ptr (tr)); tr->RecordEnableChanged.connect_same_thread (*this, boost::bind (&Session::update_have_rec_enabled_track, this)); + + boost::shared_ptr mt = boost::dynamic_pointer_cast (tr); + if (mt) { + mt->StepEditStatusChange.connect_same_thread (*this, boost::bind (&Session::step_edit_status_change, this, _1)); + } } } @@ -2103,6 +2112,13 @@ Session::remove_route (shared_ptr route) } } + boost::shared_ptr mt = boost::dynamic_pointer_cast (route); + if (mt && mt->step_editing()) { + if (_step_editors > 0) { + _step_editors--; + } + } + update_latency_compensation (false, false); set_dirty(); @@ -3922,3 +3938,28 @@ Session::route_order_key_changed () { RouteOrderKeyChanged (); /* EMIT SIGNAL */ } + +void +Session::step_edit_status_change (bool yn) +{ + bool send = false; + + bool val = false; + if (yn) { + send = (_step_editors == 0); + val = true; + + _step_editors++; + } else { + send = (_step_editors == 1); + val = false; + + if (_step_editors > 0) { + _step_editors--; + } + } + + if (send) { + StepEditStatusChange (val); + } +} diff --git a/libs/ardour/session_midi.cc b/libs/ardour/session_midi.cc index 3939b544b4..2ce3310f47 100644 --- a/libs/ardour/session_midi.cc +++ b/libs/ardour/session_midi.cc @@ -130,7 +130,7 @@ Session::mmc_record_pause (MIDI::MachineControl &/*mmc*/) void Session::mmc_record_strobe (MIDI::MachineControl &/*mmc*/) { - if (!Config->get_mmc_control()) { + if (!Config->get_mmc_control() || (_step_editors > 0)) { return; } @@ -335,7 +335,7 @@ Session::mmc_record_enable (MIDI::MachineControl &mmc, size_t trk, bool enabled) if ((at = dynamic_cast((*i).get())) != 0) { if (trk == at->remote_control_id()) { - at->set_record_enable (enabled, &mmc); + at->set_record_enabled (enabled, &mmc); break; } } diff --git a/libs/ardour/session_rtevents.cc b/libs/ardour/session_rtevents.cc index 921a6348eb..ff452137d9 100644 --- a/libs/ardour/session_rtevents.cc +++ b/libs/ardour/session_rtevents.cc @@ -148,17 +148,17 @@ Session::rt_set_solo_isolated (boost::shared_ptr rl, bool yn, bool /* } void -Session::set_record_enable (boost::shared_ptr rl, bool yn, SessionEvent::RTeventCallback after, bool group_override) +Session::set_record_enabled (boost::shared_ptr rl, bool yn, SessionEvent::RTeventCallback after, bool group_override) { if (!writable()) { return; } - queue_event (get_rt_event (rl, yn, after, group_override, &Session::rt_set_record_enable)); + queue_event (get_rt_event (rl, yn, after, group_override, &Session::rt_set_record_enabled)); } void -Session::rt_set_record_enable (boost::shared_ptr rl, bool yn, bool group_override) +Session::rt_set_record_enabled (boost::shared_ptr rl, bool yn, bool group_override) { for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) { if ((*i)->is_hidden()) { @@ -168,7 +168,7 @@ Session::rt_set_record_enable (boost::shared_ptr rl, bool yn, bool gr boost::shared_ptr t; if ((t = boost::dynamic_pointer_cast(*i)) != 0) { - t->set_record_enable (yn, (group_override ? (void*) t->route_group() : (void *) this)); + t->set_record_enabled (yn, (group_override ? (void*) t->route_group() : (void *) this)); } } diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index 6c6da8702d..94ea4bb2a1 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -216,6 +216,7 @@ Session::first_stage_init (string fullpath, string snapshot_name) first_file_header_format_reset = true; post_export_sync = false; midi_control_ui = 0; + _step_editors = 0; AudioDiskstream::allocate_working_buffers(); diff --git a/libs/ardour/track.cc b/libs/ardour/track.cc index 23afe6dea2..145251a021 100644 --- a/libs/ardour/track.cc +++ b/libs/ardour/track.cc @@ -132,7 +132,7 @@ void Track::RecEnableControllable::set_value (float val) { bool bval = ((val >= 0.5f) ? true: false); - track.set_record_enable (bval, this); + track.set_record_enabled (bval, this); } float @@ -161,7 +161,7 @@ Track::can_record() } void -Track::set_record_enable (bool yn, void *src) +Track::set_record_enabled (bool yn, void *src) { if (!_session.writable()) { return; @@ -172,7 +172,7 @@ Track::set_record_enable (bool yn, void *src) } if (_route_group && src != _route_group && _route_group->is_active() && _route_group->is_recenable()) { - _route_group->apply (&Track::set_record_enable, yn, _route_group); + _route_group->apply (&Track::set_record_enabled, yn, _route_group); return; } @@ -599,12 +599,6 @@ Track::alignment_style () const return _diskstream->alignment_style (); } -void -Track::set_record_enabled (bool r) -{ - _diskstream->set_record_enabled (r); -} - nframes_t Track::current_capture_start () const { diff --git a/libs/evoral/src/ControlList.cpp b/libs/evoral/src/ControlList.cpp index bfe4c95365..4a710cfbb0 100644 --- a/libs/evoral/src/ControlList.cpp +++ b/libs/evoral/src/ControlList.cpp @@ -1020,10 +1020,11 @@ ControlList::rt_safe_earliest_event_linear_unlocked (double start, double end, d //<< ", x: " << x << ", y: " << y << ", inclusive: " << inclusive << ")" << endl; const_iterator length_check_iter = _events.begin(); - if (_events.empty()) // 0 events + if (_events.empty()) { // 0 events return false; - else if (_events.end() == ++length_check_iter) // 1 event + } else if (_events.end() == ++length_check_iter) { // 1 event return rt_safe_earliest_event_discrete_unlocked(start, end, x, y, inclusive); + } // Hack to avoid infinitely repeating the same event build_search_cache_if_necessary(start, end); diff --git a/libs/surfaces/control_protocol/control_protocol.cc b/libs/surfaces/control_protocol/control_protocol.cc index 62214e6429..cf98b66b5e 100644 --- a/libs/surfaces/control_protocol/control_protocol.cc +++ b/libs/surfaces/control_protocol/control_protocol.cc @@ -190,7 +190,7 @@ ControlProtocol::route_set_rec_enable (uint32_t table_index, bool yn) boost::shared_ptr at = boost::dynamic_pointer_cast(r); if (at) { - at->set_record_enable (yn, this); + at->set_record_enabled (yn, this); } } diff --git a/libs/surfaces/mackie/mackie_control_protocol.cc b/libs/surfaces/mackie/mackie_control_protocol.cc index 073d0c475f..5802e80b1a 100644 --- a/libs/surfaces/mackie/mackie_control_protocol.cc +++ b/libs/surfaces/mackie/mackie_control_protocol.cc @@ -403,7 +403,7 @@ MackieControlProtocol::handle_strip_button (Control & control, ButtonState bs, b if (control.name() == "recenable") { state = !route->record_enabled(); - route->set_record_enable (state, this); + route->set_record_enabled (state, this); } else if (control.name() == "mute") { diff --git a/libs/surfaces/osc/osc.cc b/libs/surfaces/osc/osc.cc index 937cf6ae29..d52348ef5c 100644 --- a/libs/surfaces/osc/osc.cc +++ b/libs/surfaces/osc/osc.cc @@ -748,7 +748,7 @@ OSC::route_recenable (int rid, int yn) boost::shared_ptr r = session->route_by_remote_id (rid); if (r) { - r->set_record_enable (yn, this); + r->set_record_enabled (yn, this); } return 0; }