diff --git a/gtk2_ardour/editing_context.cc b/gtk2_ardour/editing_context.cc index 93de061ef9..bc9dc566e0 100644 --- a/gtk2_ardour/editing_context.cc +++ b/gtk2_ardour/editing_context.cc @@ -3297,3 +3297,45 @@ EditingContext::update_grid () } } +Location* +EditingContext::transport_loop_location() +{ + if (_session) { + return _session->locations()->auto_loop_location(); + } else { + return 0; + } +} + +void +EditingContext::set_loop_range (timepos_t const & start, timepos_t const & end, string cmd) +{ + if (!_session) { + return; + } + if (_session->get_play_loop () && _session->actively_recording ()) { + return; + } + + begin_reversible_command (cmd); + + Location* tll; + + if ((tll = transport_loop_location()) == 0) { + Location* loc = new Location (*_session, start, end, _("Loop"), Location::IsAutoLoop); + XMLNode &before = _session->locations()->get_state(); + _session->locations()->add (loc, true); + _session->set_auto_loop_location (loc); + XMLNode &after = _session->locations()->get_state(); + add_command (new MementoCommand(*(_session->locations()), &before, &after)); + } else { + XMLNode &before = tll->get_state(); + tll->set_hidden (false, this); + tll->set (start, end); + XMLNode &after = tll->get_state(); + add_command (new MementoCommand(*tll, &before, &after)); + } + + commit_reversible_command (); +} + diff --git a/gtk2_ardour/editing_context.h b/gtk2_ardour/editing_context.h index a071de1944..bce45c0fae 100644 --- a/gtk2_ardour/editing_context.h +++ b/gtk2_ardour/editing_context.h @@ -477,6 +477,8 @@ class EditingContext : public ARDOUR::SessionHandlePtr, public AxisViewProvider, virtual void update_grid (); + void set_loop_range (Temporal::timepos_t const & start, Temporal::timepos_t const & end, std::string cmd); + protected: std::string _name; bool within_track_canvas; @@ -760,6 +762,8 @@ class EditingContext : public ARDOUR::SessionHandlePtr, public AxisViewProvider, bool clear_entered_track; + ARDOUR::Location* transport_loop_location(); + std::vector grid_marks; GridLines* grid_lines; ArdourCanvas::Container* time_line_group; diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc index 6cfb41aa52..66c66bebcd 100644 --- a/gtk2_ardour/editor.cc +++ b/gtk2_ardour/editor.cc @@ -3632,16 +3632,6 @@ Editor::finish_cleanup () _regions->resume_redisplay (); } -Location* -Editor::transport_loop_location() -{ - if (_session) { - return _session->locations()->auto_loop_location(); - } else { - return 0; - } -} - Location* Editor::transport_punch_location() { @@ -4146,38 +4136,6 @@ Editor::_get_preferred_edit_position (EditIgnoreOption ignore, bool from_context return where; } -void -Editor::set_loop_range (timepos_t const & start, timepos_t const & end, string cmd) -{ - if (!_session) { - return; - } - if (_session->get_play_loop () && _session->actively_recording ()) { - return; - } - - begin_reversible_command (cmd); - - Location* tll; - - if ((tll = transport_loop_location()) == 0) { - Location* loc = new Location (*_session, start, end, _("Loop"), Location::IsAutoLoop); - XMLNode &before = _session->locations()->get_state(); - _session->locations()->add (loc, true); - _session->set_auto_loop_location (loc); - XMLNode &after = _session->locations()->get_state(); - _session->add_command (new MementoCommand(*(_session->locations()), &before, &after)); - } else { - XMLNode &before = tll->get_state(); - tll->set_hidden (false, this); - tll->set (start, end); - XMLNode &after = tll->get_state(); - _session->add_command (new MementoCommand(*tll, &before, &after)); - } - - commit_reversible_command (); -} - void Editor::set_punch_range (timepos_t const & start, timepos_t const & end, string cmd) { diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index 7b37fc1e93..88be6e4c5a 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -1423,7 +1423,6 @@ private: void set_loop_from_region (bool play); - void set_loop_range (Temporal::timepos_t const & start, Temporal::timepos_t const & end, std::string cmd); void set_punch_range (Temporal::timepos_t const & start, Temporal::timepos_t const & end, std::string cmd); void add_tempo_from_playhead_cursor (); @@ -1864,7 +1863,6 @@ private: ArdourCanvas::Rectangle* transport_preroll_rect; ArdourCanvas::Rectangle* transport_postroll_rect; - ARDOUR::Location* transport_loop_location(); ARDOUR::Location* transport_punch_location(); ARDOUR::Location* temp_location; diff --git a/gtk2_ardour/pianoroll.cc b/gtk2_ardour/pianoroll.cc index 463a7967ca..7705f15fad 100644 --- a/gtk2_ardour/pianoroll.cc +++ b/gtk2_ardour/pianoroll.cc @@ -72,6 +72,7 @@ Pianoroll::Pianoroll (std::string const & name) , bbt_metric (*this) , _note_mode (Sustained) , zoom_in_allocate (false) + , solo_button (S_("Solo|S")) , bar_adjustment (4, 1, 32, 1, 4) , bar_spinner (bar_adjustment) , length_label (X_("Record (Bars):")) @@ -385,9 +386,29 @@ Pianoroll::build_upper_toolbar () note_mode_button.set_size_request (PX_SCALE(50), -1); note_mode_button.set_active_color (UIConfiguration::instance().color ("alert:yellow")); + + play_button.set_icon (ArdourIcon::TransportPlay); + loop_button.set_icon (ArdourIcon::TransportLoop); + + solo_button.set_name ("solo button"); + + play_box.set_spacing (8); + play_box.pack_start (play_button, false, false); + play_box.pack_start (loop_button, false, false); + play_box.pack_start (solo_button, false, false); + play_button.show(); + loop_button.show(); + solo_button.show(); + play_box.set_no_show_all (true); + play_box.show (); + play_button.signal_button_release_event().connect (sigc::mem_fun (*this, &Pianoroll::play_button_press), false); + solo_button.signal_button_release_event().connect (sigc::mem_fun (*this, &Pianoroll::solo_button_press), false); + loop_button.signal_button_release_event().connect (sigc::mem_fun (*this, &Pianoroll::loop_button_press), false); + rec_enable_button.set_icon (ArdourIcon::RecButton); rec_enable_button.set_sensitive (false); rec_enable_button.signal_button_release_event().connect (sigc::mem_fun (*this, &Pianoroll::rec_button_press), false); + rec_enable_button.set_name ("record enable button"); rec_box.set_spacing (12); rec_box.pack_start (rec_enable_button, false, false); @@ -401,6 +422,7 @@ Pianoroll::build_upper_toolbar () _toolbar_outer->set_border_width (6); _toolbar_outer->set_spacing (12); + _toolbar_outer->pack_start (play_box, false, false); _toolbar_outer->pack_start (rec_box, false, false); _toolbar_outer->pack_start (visible_channel_label, false, false); _toolbar_outer->pack_start (visible_channel_selector, false, false); @@ -2126,6 +2148,49 @@ Pianoroll::rec_enable_change () } } +bool +Pianoroll::play_button_press (GdkEventButton* ev) +{ + _session->request_locate (view->midi_region()->position().samples()); + _session->request_roll (); + return true; +} + +bool +Pianoroll::loop_button_press (GdkEventButton* ev) +{ + if (!view) { + return true; + } + if (!view->midi_region()) { + return true; + } + + if (_session->get_play_loop()) { + _session->request_play_loop (false); + } else { + set_loop_range (view->midi_region()->position(), view->midi_region()->end(), _("loop region")); + _session->request_play_loop (true); + } + + return true; +} + +bool +Pianoroll::solo_button_press (GdkEventButton* ev) +{ + if (!view) { + return true; + } + + if (!view->midi_track()) { + return true; + } + + view->midi_track()->solo_control()->set_value (!view->midi_track()->solo_control()->get_value(), Controllable::NoGroup); + + return true; +} bool Pianoroll::rec_button_press (GdkEventButton* ev) @@ -2239,11 +2304,24 @@ Pianoroll::set_track (std::shared_ptr track) sigc::bind (sigc::mem_fun (*this, &Pianoroll::add_single_controller_item), cc_dropdown3), sigc::bind (sigc::mem_fun (*this, &Pianoroll::add_multi_controller_item), cc_dropdown3)); + track->solo_control()->Changed.connect (object_connections, invalidator (*this), std::bind (&Pianoroll::update_solo_display, this), gui_context()); + update_solo_display (); + // reset_user_cc_choice (Evoral::Parameter (ARDOUR::MidiCCAutomation, _visible_channel, MIDI_CTL_MSB_GENERAL_PURPOSE1), cc_dropdown1); // reset_user_cc_choice (Evoral::Parameter (ARDOUR::MidiCCAutomation, _visible_channel, MIDI_CTL_MSB_GENERAL_PURPOSE2), cc_dropdown2); // reset_user_cc_choice (Evoral::Parameter (ARDOUR::MidiCCAutomation, _visible_channel, MIDI_CTL_MSB_GENERAL_PURPOSE3), cc_dropdown3); } +void +Pianoroll::update_solo_display () +{ + if (view->midi_track()->solo_control()->get_value()) { + solo_button.set_active_state (Gtkmm2ext::ExplicitActive); + } else { + solo_button.set_active_state (Gtkmm2ext::Off); + } +} + void Pianoroll::set_region (std::shared_ptr r) { diff --git a/gtk2_ardour/pianoroll.h b/gtk2_ardour/pianoroll.h index 6b629e55c5..827836dd64 100644 --- a/gtk2_ardour/pianoroll.h +++ b/gtk2_ardour/pianoroll.h @@ -291,11 +291,19 @@ class Pianoroll : public CueEditor bool zoom_in_allocate; ArdourWidgets::ArdourButton rec_enable_button; - void rec_enable_clicked (); + ArdourWidgets::ArdourButton play_button; + ArdourWidgets::ArdourButton solo_button; + ArdourWidgets::ArdourButton loop_button; + + bool play_button_press (GdkEventButton*); + bool solo_button_press (GdkEventButton*); + bool loop_button_press (GdkEventButton*); + Gtk::Adjustment bar_adjustment; Gtk::SpinButton bar_spinner; Gtk::Label length_label; Gtk::HBox rec_box; + Gtk::HBox play_box; bool rec_button_press (GdkEventButton*); void rec_enable_change (); @@ -309,4 +317,5 @@ class Pianoroll : public CueEditor bool ignore_channel_changes; void visible_channel_changed (); + void update_solo_display (); }; diff --git a/gtk2_ardour/public_editor.h b/gtk2_ardour/public_editor.h index e2268fbbb1..b1dda8def2 100644 --- a/gtk2_ardour/public_editor.h +++ b/gtk2_ardour/public_editor.h @@ -192,7 +192,6 @@ public: } virtual void add_location_mark_with_flag (Temporal::timepos_t const & where, ARDOUR::Location::Flags, int32_t cue_id) = 0; virtual void remove_tracks () = 0; - virtual void set_loop_range (Temporal::timepos_t const & start, Temporal::timepos_t const & end, std::string cmd) = 0; virtual void set_punch_range (Temporal::timepos_t const & start, Temporal::timepos_t const & end, std::string cmd) = 0; void jump_forward_to_mark () {