step editing now accessed via a context menu on MIDI track rec-enable buttons. along...
authorPaul Davis <paul@linuxaudiosystems.com>
Sat, 24 Jul 2010 16:40:56 +0000 (16:40 +0000)
committerPaul Davis <paul@linuxaudiosystems.com>
Sat, 24 Jul 2010 16:40:56 +0000 (16:40 +0000)
git-svn-id: svn://localhost/ardour2/branches/3.0@7482 d708f5d6-7413-0410-9779-e7cbd77b26cf

29 files changed:
gtk2_ardour/ardour3_ui_dark.rc.in
gtk2_ardour/ardour_ui.cc
gtk2_ardour/ardour_ui.h
gtk2_ardour/ardour_ui_dialogs.cc
gtk2_ardour/editor.cc
gtk2_ardour/editor.h
gtk2_ardour/editor_mouse.cc
gtk2_ardour/editor_ops.cc
gtk2_ardour/editor_routes.cc
gtk2_ardour/midi_time_axis.cc
gtk2_ardour/midi_time_axis.h
gtk2_ardour/route_time_axis.cc
gtk2_ardour/route_ui.cc
gtk2_ardour/route_ui.h
libs/ardour/ardour/midi_track.h
libs/ardour/ardour/public_diskstream.h
libs/ardour/ardour/route.h
libs/ardour/ardour/session.h
libs/ardour/ardour/track.h
libs/ardour/midi_track.cc
libs/ardour/session.cc
libs/ardour/session_midi.cc
libs/ardour/session_rtevents.cc
libs/ardour/session_state.cc
libs/ardour/track.cc
libs/evoral/src/ControlList.cpp
libs/surfaces/control_protocol/control_protocol.cc
libs/surfaces/mackie/mackie_control_protocol.cc
libs/surfaces/osc/osc.cc

index 1be6acbb9dcad342f4bee53f29b9d6954881cc91..dc560699d05ff48c3201f30faf0be9ba2365f365 100644 (file)
@@ -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"
index 9cc879c3ffac20c382dcc2919d709fa93255a1d9..9d789c20be49810d989cf112b1d3464bf96b925d 100644 (file)
@@ -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<Route> 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<Track*>(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 ()
 {
index 4e8137d76eb92ede953a1d4b61713d8a8f1f8fda..04cd080ac3f6a9ad8cf4ff6dc22fd968208e6f5b 100644 (file)
@@ -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__ */
index c187a5df56be3f459a24ba3eba0590c44f133fad..747354ca4e8a02c09c978be0e2f6dd9249ba7845 100644 (file)
@@ -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());
 
index 49470849c6042f238b380315a4ba6c225132b6a3..7f19e1e415000ce077b3c725a8d38a7e0d473a86 100644 (file)
@@ -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();
        }
 }
+
index 167872fcdd7d17eabeae190cc06952f8e3ccb7d5..15758b97fbabbebd1d1edfa1690564133b3ed40c 100644 (file)
@@ -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 ();
index 030205476082a455f147194edd8fac5386121518..da2ee66a0fec386d7c0db4d1103bf2cf30592a31 100644 (file)
@@ -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<MidiTimeAxisView*> (*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<MidiTimeAxisView*> (*i);
-                       if (mtv) {
-                               mtv->stop_step_editing ();
-                       }
-               }
-
-                mouse_mode_toggled (mouse_mode);
+                mouse_mode_toggled (mouse_mode); // sets cursor
        }
 }
 
index adc9078fba04fe48720120de00f86d50a88a826d..cb76fcb1ec7b3cda0c83477ebe611bf274a2a9b3 100644 (file)
@@ -5116,7 +5116,7 @@ Editor::toggle_record_enable ()
                        first = false;
                }
 
-               rtav->track()->set_record_enable(new_state, this);
+               rtav->track()->set_record_enable(new_state, this);
        }
 }
 
index 308f0c50b81d6266b4dd328c3984466e66d29a1b..81e56c3e326f88c15646dd1c00b55f1a27e13a3a 100644 (file)
@@ -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<RouteList> 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);
        }
 }
 
index a4e09871c92b0e681f16d1468858e6280b6c7cbb..cb4eb795bdaf9516dec2706b53a93eb08fa13cd1 100644 (file)
@@ -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<Region>
-MidiTimeAxisView::add_region (nframes64_t pos)
+MidiTimeAxisView::add_region (framepos_t pos)
 {
        Editor* real_editor = dynamic_cast<Editor*> (&_editor);
 
index e15167f855c2ac3ef62dc3c1b583f8537d1a3931..b118b9ab6314248bcccfd073bbadefa869fdf6e0 100644 (file)
@@ -67,7 +67,7 @@ class MidiTimeAxisView : public RouteTimeAxisView
        void set_height (uint32_t);
        void hide ();
 
-       boost::shared_ptr<ARDOUR::Region> add_region (nframes64_t pos);
+       boost::shared_ptr<ARDOUR::Region> 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 ();
index 49c49a3734399723c44e7e110bc70b2e87fe6bbe..d1df63d187bd91a78b15614ce2efbac66f6a076b 100644 (file)
@@ -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());
        }
index 71d38360d529dadae48687662121f68d797d2026..6e9f5a73d1912811bf289a4465cf00f225eca5cc 100644 (file)
@@ -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<Route> 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<RouteList> 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;
 }
 
+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<CheckMenuItem*> (&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*)
+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);
index cc11b1809470f69aaf2eaf773117116e4fcafbd5..8d819de50508a0eddbcc1e3b9d5afc24274cceef 100644 (file)
@@ -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;
index 42446da70d34bbe799d1cedb94a5466938c66606..df1d2e11df7757d3262fb2cd76d96e72243fac62 100644 (file)
@@ -46,6 +46,7 @@ public:
 
        void use_new_diskstream ();
         void set_diskstream (boost::shared_ptr<Diskstream>);
+       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<nframes_t>& step_edit_ring_buffer() { return _step_edit_ring_buffer; }
 
+        static PBD::Signal1<void,bool> 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<MidiPlaylist> midi_playlist ();
-       
+
 protected:
        XMLNode& state (bool full);
        
index a33c43f0cdc339099692091df21766d3029e4e33..5c2c6d9fc60141f183cfc7226276383924c4c3fa 100755 (executable)
@@ -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;
index 7692583feb7822f1153fabfeccbb8656b217ca2b..54eb41f97b9b9109ba657335b86624591993a184 100644 (file)
@@ -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);
index 18ef620a89ee155bc60f8f87ae4d4027b7a74797..4627204888437a4814d16078b1822e15938572c6 100644 (file)
@@ -282,6 +282,9 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
        /** Emitted when anything about any of our route groups changes */
        PBD::Signal0<void> RouteGroupChanged;
 
+        /* Step Editing status changed */
+        PBD::Signal1<void,bool> 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<Route>, bool, SessionEvent::RTeventCallback after = rt_cleanup);
        void set_mute (boost::shared_ptr<RouteList>, bool, SessionEvent::RTeventCallback after = rt_cleanup, bool group_override = false);
        void set_listen (boost::shared_ptr<RouteList>, bool, SessionEvent::RTeventCallback after = rt_cleanup, bool group_override = false);
-       void set_record_enable (boost::shared_ptr<RouteList>, bool, SessionEvent::RTeventCallback after = rt_cleanup, bool group_override = false);
+       void set_record_enabled (boost::shared_ptr<RouteList>, bool, SessionEvent::RTeventCallback after = rt_cleanup, bool group_override = false);
         void set_solo_isolated (boost::shared_ptr<RouteList>, bool, SessionEvent::RTeventCallback after = rt_cleanup, bool group_override = false);
 
        PBD::Signal1<void,bool> SoloActive;
@@ -776,6 +779,8 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
 
        PBD::Signal0<void> 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<RouteList>, bool yn, bool group_override);
        void rt_set_listen (boost::shared_ptr<RouteList>, bool yn, bool group_override);
        void rt_set_solo_isolated (boost::shared_ptr<RouteList>, bool yn, bool group_override);
-       void rt_set_record_enable (boost::shared_ptr<RouteList>, bool yn, bool group_override);
+       void rt_set_record_enabled (boost::shared_ptr<RouteList>, bool yn, bool group_override);
 
        /** temporary list of Diskstreams used only during load of 2.X sessions */
        std::list<boost::shared_ptr<Diskstream> > _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
index 60e628af79c21e69caeb2bd9d8fab08f62ef7ebb..b3d69e440333a29ebc7e6bacb7fde54de9a69824 100644 (file)
@@ -90,7 +90,7 @@ class Track : public Route, public PublicDiskstream
        boost::shared_ptr<PBD::Controllable> 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 ();
index 3c4326621950a6d289c31268ac9c33e9b9129dce..9dced1e0b95cae96b3ab81ca6234a58d18ad48ca 100644 (file)
@@ -49,6 +49,8 @@ using namespace std;
 using namespace ARDOUR;
 using namespace PBD;
 
+PBD::Signal1<void,bool> 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<Diskstream> 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
index 45de1db1f59eeca44710673f49ca6e4a429c6aa4..71277fa3cf8d48779311fa2ad1b4fd05b2d7868a 100644 (file)
@@ -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<Track> (tr)));
                        track_playlist_changed (boost::weak_ptr<Track> (tr));
                        tr->RecordEnableChanged.connect_same_thread (*this, boost::bind (&Session::update_have_rec_enabled_track, this));
+
+                        boost::shared_ptr<MidiTrack> mt = boost::dynamic_pointer_cast<MidiTrack> (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> route)
                }
        }       
 
+        boost::shared_ptr<MidiTrack> mt = boost::dynamic_pointer_cast<MidiTrack> (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);
+        }
+}
index 3939b544b498b98e4f639fd7e3bf4d9c1f1ff51a..2ce3310f47340ebf7ef2db4d20fdbdf97c962396 100644 (file)
@@ -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<AudioTrack*>((*i).get())) != 0) {
                                if (trk == at->remote_control_id()) {
-                                       at->set_record_enable (enabled, &mmc);
+                                       at->set_record_enabled (enabled, &mmc);
                                        break;
                                }
                        }
index 921a6348ebdd87cfc7fd507cf2700ceaf4203e56..ff452137d9a8193b32c919af2e3c948875948d3b 100644 (file)
@@ -148,17 +148,17 @@ Session::rt_set_solo_isolated (boost::shared_ptr<RouteList> rl, bool yn, bool /*
 }
 
 void
-Session::set_record_enable (boost::shared_ptr<RouteList> rl, bool yn, SessionEvent::RTeventCallback after, bool group_override)
+Session::set_record_enabled (boost::shared_ptr<RouteList> 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<RouteList> rl, bool yn, bool group_override)
+Session::rt_set_record_enabled (boost::shared_ptr<RouteList> 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<RouteList> rl, bool yn, bool gr
                boost::shared_ptr<Track> t;
 
                if ((t = boost::dynamic_pointer_cast<Track>(*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));
                }
        }
 
index 6c6da8702d6df602a872809eb2e40ffebb08ebf8..94ea4bb2a1a78707805137b49581104c6160d260 100644 (file)
@@ -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();
 
index 23afe6dea2ab5fdb5e9b58ff48ffe412ece6c58a..145251a02155eefed1f0259a3ddd956be063b0ea 100644 (file)
@@ -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
 {
index bfe4c953659fd3fa0adbb28d6859fae82ef51078..4a710cfbb063221af71d9a76c40d4d9b54f60c61 100644 (file)
@@ -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);
index 62214e6429031da68b35d1ca7b6357911a49bbda..cf98b66b5e4941679e30e7261dcdc7699718c30d 100644 (file)
@@ -190,7 +190,7 @@ ControlProtocol::route_set_rec_enable (uint32_t table_index, bool yn)
        boost::shared_ptr<AudioTrack> at = boost::dynamic_pointer_cast<AudioTrack>(r);
 
        if (at) {
-               at->set_record_enable (yn, this);
+               at->set_record_enabled (yn, this);
        }
 }
 
index 073d0c475fac7030526da8505a795d0b2e6c4cca..5802e80b1ad44c768299c1275fbdbbfca415ba5c 100644 (file)
@@ -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")
                {
index 937cf6ae29dcf9d9193224961b976706f6481bf6..d52348ef5c6bb7e094b7bb6358c70738b5966db6 100644 (file)
@@ -748,7 +748,7 @@ OSC::route_recenable (int rid, int yn)
        boost::shared_ptr<Route> r = session->route_by_remote_id (rid);
 
        if (r) {
-               r->set_record_enable (yn, this);
+               r->set_record_enabled (yn, this);
        }
        return 0;
 }