#include "ardour/audio_track.h"
#include "ardour/audioengine.h"
#include "ardour/audioregion.h"
+#include "ardour/lmath.h"
#include "ardour/location.h"
#include "ardour/profile.h"
#include "ardour/route_group.h"
#include "control_protocol/control_protocol.h"
-#include "actions.h"
#include "actions.h"
#include "analysis_window.h"
#include "audio_clock.h"
Editor::Editor ()
: _join_object_range_state (JOIN_OBJECT_RANGE_NONE)
+ , _mouse_changed_selection (false)
/* time display buttons */
, minsec_label (_("Mins:Secs"))
, bbt_label (_("Bars:Beats"))
location_loop_color = ARDOUR_UI::config()->color ("location loop");
location_punch_color = ARDOUR_UI::config()->color ("location punch");
- zoom_focus = ZoomFocusLeft;
+ zoom_focus = ZoomFocusPlayhead;
_edit_point = EditAtMouse;
_visible_track_count = -1;
edit_items.push_back (MenuElem (_("Bounce Range to Region List With Processing"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), false, true)));
edit_items.push_back (MenuElem (_("Export Range..."), sigc::mem_fun(*this, &Editor::export_selection)));
if (ARDOUR_UI::instance()->video_timeline->get_duration() > 0) {
- edit_items.push_back (MenuElem (_("Export Video Range..."), sigc::bind (sigc::mem_fun(*this, &Editor::export_video), true)));
+ edit_items.push_back (MenuElem (_("Export Video Range..."), sigc::bind (sigc::mem_fun(*(ARDOUR_UI::instance()), &ARDOUR_UI::export_video), true)));
}
}
if ((prop = node.property ("show-measures"))) {
bool yn = string_is_affirmative (prop->value());
_show_measures = yn;
- RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("ToggleMeasureVisibility"));
- if (act) {
- RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
- /* do it twice to force the change */
- tact->set_active (!yn);
- tact->set_active (yn);
- }
}
if ((prop = node.property ("follow-playhead"))) {
bool yn = string_is_affirmative (prop->value());
set_follow_playhead (yn);
- RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-follow-playhead"));
- if (act) {
- RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
- if (tact->get_active() != yn) {
- tact->set_active (yn);
- }
- }
}
if ((prop = node.property ("stationary-playhead"))) {
bool yn = string_is_affirmative (prop->value());
set_stationary_playhead (yn);
- RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-stationary-playhead"));
- if (act) {
- RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
- if (tact->get_active() != yn) {
- tact->set_active (yn);
- }
- }
}
if ((prop = node.property ("region-list-sort-type"))) {
nudge_clock->set (_session->frame_rate() * 5, true);
}
+ {
+ /* apply state
+ * Not all properties may have been in XML, but
+ * those that are linked to a private variable may need changing
+ */
+ RefPtr<Action> act;
+ bool yn;
+
+ act = ActionManager::get_action (X_("Editor"), X_("ToggleMeasureVisibility"));
+ if (act) {
+ yn = _show_measures;
+ RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
+ /* do it twice to force the change */
+ tact->set_active (!yn);
+ tact->set_active (yn);
+ }
+
+ act = ActionManager::get_action (X_("Editor"), X_("toggle-follow-playhead"));
+ yn = _follow_playhead;
+ if (act) {
+ RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
+ if (tact->get_active() != yn) {
+ tact->set_active (yn);
+ }
+ }
+
+ act = ActionManager::get_action (X_("Editor"), X_("toggle-stationary-playhead"));
+ yn = _stationary_playhead;
+ if (act) {
+ RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
+ if (tact->get_active() != yn) {
+ tact->set_active (yn);
+ }
+ }
+ }
+
return 0;
}
void
Editor::setup_tooltips ()
{
- ARDOUR_UI::instance()->set_tip (smart_mode_button, _("Smart Mode (add Range functions to Object mode)"));
- ARDOUR_UI::instance()->set_tip (mouse_move_button, _("Object Mode (select/move Objects)"));
- ARDOUR_UI::instance()->set_tip (mouse_cut_button, _("Cut Mode (split Regions)"));
- ARDOUR_UI::instance()->set_tip (mouse_select_button, _("Grab/Select Objects"));
- ARDOUR_UI::instance()->set_tip (mouse_draw_button, _("Draw/Edit Gain/Notes/Automation"));
- ARDOUR_UI::instance()->set_tip (mouse_timefx_button, _("Stretch/Shrink Regions and MIDI Notes"));
- ARDOUR_UI::instance()->set_tip (mouse_audition_button, _("Listen to Specific Regions"));
- ARDOUR_UI::instance()->set_tip (mouse_content_button, _("Edit Contents (notes and automation)"));
+ ARDOUR_UI::instance()->set_tip (smart_mode_button, _("Smart Mode (add Range functions to Grab mode)"));
+ ARDOUR_UI::instance()->set_tip (mouse_move_button, _("Grab Mode (select/move objects)"));
+ ARDOUR_UI::instance()->set_tip (mouse_cut_button, _("Cut Mode (split regions)"));
+ ARDOUR_UI::instance()->set_tip (mouse_select_button, _("Range Mode (select time ranges)"));
+ ARDOUR_UI::instance()->set_tip (mouse_draw_button, _("Draw Mode (draw and edit gain/notes/automation)"));
+ ARDOUR_UI::instance()->set_tip (mouse_timefx_button, _("Stretch Mode (time-stretch audio and midi regions, preserving pitch)"));
+ ARDOUR_UI::instance()->set_tip (mouse_audition_button, _("Audition Mode (listen to regions)"));
+ ARDOUR_UI::instance()->set_tip (mouse_content_button, _("Internal Edit Mode (edit notes and gain curves inside regions)"));
ARDOUR_UI::instance()->set_tip (*_group_tabs, _("Groups: click to (de)activate\nContext-click for other operations"));
ARDOUR_UI::instance()->set_tip (nudge_forward_button, _("Nudge Region/Selection Later"));
ARDOUR_UI::instance()->set_tip (nudge_backward_button, _("Nudge Region/Selection Earlier"));
{
selection_op_cmd_depth = 0;
selection_op_history_it = 0;
- selection_op_history.clear();
+
+ while(!selection_op_history.empty()) {
+ delete selection_op_history.front();
+ selection_op_history.pop_front();
+ }
+
selection_undo_action->set_sensitive (false);
selection_redo_action->set_sensitive (false);
selection_op_history.push_front (&_selection_memento->get_state ());
if (selection_op_cmd_depth == 1) {
if (selection_op_history_it > 0 && selection_op_history_it < selection_op_history.size()) {
+ /**
+ The user has undone some selection ops and then made a new one,
+ making anything earlier in the list invalid.
+ */
+
list<XMLNode *>::iterator it = selection_op_history.begin();
- advance (it, selection_op_history_it);
- selection_op_history.erase (selection_op_history.begin(), it);
+ list<XMLNode *>::iterator e_it = it;
+ advance (e_it, selection_op_history_it);
+
+ for ( ; it != e_it; ++it) {
+ delete *it;
+ }
+ selection_op_history.erase (selection_op_history.begin(), e_it);
}
+
selection_op_history.push_front (&_selection_memento->get_state ());
selection_op_history_it = 0;
+
+ selection_undo_action->set_sensitive (true);
+ selection_redo_action->set_sensitive (false);
}
if (selection_op_cmd_depth > 0) {
selection_op_cmd_depth--;
}
-
- selection_undo_action->set_sensitive (true);
- selection_redo_action->set_sensitive (false);
}
}
selection_redo_action->set_sensitive (true);
}
++n;
-
}
/* is there an earlier entry? */
if ((selection_op_history_it + 1) >= selection_op_history.size()) {
selection_undo_action->set_sensitive (true);
}
++n;
-
}
if (selection_op_history_it == 0) {
}
}
+void
+Editor::abort_reversible_command ()
+{
+ if (_session) {
+ while(!before.empty()) {
+ delete before.front();
+ before.pop_front();
+ }
+ _session->abort_reversible_command ();
+ }
+}
+
void
Editor::commit_reversible_command ()
{
if (_session) {
if (before.size() == 1) {
_session->add_command (new MementoCommand<SelectionMemento>(*(_selection_memento), before.front(), &_selection_memento->get_state ()));
+ redo_action->set_sensitive(false);
undo_action->set_sensitive(true);
begin_selection_op_history ();
}
visible_tracks_selector.AddMenuElem (MenuElem (X_("24"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 24)));
visible_tracks_selector.AddMenuElem (MenuElem (X_("32"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 32)));
visible_tracks_selector.AddMenuElem (MenuElem (X_("64"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 64)));
- visible_tracks_selector.AddMenuElem (MenuElem (_("Selected"), sigc::mem_fun(*this, &Editor::fit_selected_tracks)));
+ visible_tracks_selector.AddMenuElem (MenuElem (_("Selection"), sigc::mem_fun(*this, &Editor::fit_selection)));
visible_tracks_selector.AddMenuElem (MenuElem (_("All"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 0)));
} else {
visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 1 track"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 1)));
visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 32 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 32)));
visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 48 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 48)));
visible_tracks_selector.AddMenuElem (MenuElem (_("Fit All tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 0)));
- visible_tracks_selector.AddMenuElem (MenuElem (_("Fit Selected tracks"), sigc::mem_fun(*this, &Editor::fit_selected_tracks)));
+ visible_tracks_selector.AddMenuElem (MenuElem (_("Fit Selection"), sigc::mem_fun(*this, &Editor::fit_selection)));
zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 10 ms"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 10)));
zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 100 ms"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 100)));
}
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
- (*i)->set_height (h);
+ (*i)->set_height (h, TimeAxisView::HeightPerLane);
}
if (str != visible_tracks_selector.get_text()) {
*ARDOUR_UI::instance()->gui_object_state = *vs.gui_state;
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
+ (*i)->clear_property_cache();
(*i)->reset_visual_state ();
}
}
}
framepos_t
-Editor::get_preferred_edit_position (bool ignore_playhead, bool from_context_menu)
+Editor::get_preferred_edit_position (bool ignore_playhead, bool from_context_menu, bool from_outside_canvas)
{
bool ignored;
framepos_t where = 0;
if(Profile->get_mixbus())
if (ep == EditAtSelectedMarker)
ep=EditAtPlayhead;
-
- if (from_context_menu && (ep == EditAtMouse)) {
+
+ if (from_outside_canvas && (ep == EditAtMouse)) {
+ ep = EditAtPlayhead;
+ } else if (from_context_menu && (ep == EditAtMouse)) {
return canvas_event_sample (&context_click_event, 0, 0);
}
switch (ep) {
case EditAtPlayhead:
- where = _session->audible_frame();
+ if (_dragging_playhead) {
+ if (!mouse_frame (where, ignored)) {
+ /* XXX not right but what can we do ? */
+ return 0;
+ }
+ } else
+ where = _session->audible_frame();
DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use playhead @ %1\n", where));
break;
}
void
-Editor::get_regionviews_by_id (PBD::ID const & id, RegionSelection & regions) const
+Editor::get_regionviews_by_id (PBD::ID const id, RegionSelection & regions) const
{
for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
- RouteTimeAxisView* tatv;
+ RouteTimeAxisView* rtav;
- if ((tatv = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
+ if ((rtav = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
boost::shared_ptr<Playlist> pl;
std::vector<boost::shared_ptr<Region> > results;
boost::shared_ptr<Track> tr;
- if ((tr = tatv->track()) == 0) {
+ if ((tr = rtav->track()) == 0) {
/* bus */
continue;
}
if ((pl = (tr->playlist())) != 0) {
boost::shared_ptr<Region> r = pl->region_by_id (id);
if (r) {
- RegionView* marv = tatv->view()->find_view (r);
- if (marv) {
- regions.push_back (marv);
+ RegionView* rv = rtav->view()->find_view (r);
+ if (rv) {
+ regions.push_back (rv);
}
}
}
}
}
+void
+Editor::get_per_region_note_selection (list<pair<PBD::ID, set<boost::shared_ptr<Evoral::Note<Evoral::Beats> > > > > &selection) const
+{
+
+ for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
+ MidiTimeAxisView* mtav;
+
+ if ((mtav = dynamic_cast<MidiTimeAxisView*> (*i)) != 0) {
+
+ mtav->get_per_region_note_selection (selection);
+ }
+ }
+
+}
+
void
Editor::get_regions_corresponding_to (boost::shared_ptr<Region> region, vector<RegionView*>& regions, bool src_comparison)
{
break;
}
}
+
+ MidiRegionView* mrv = dynamic_cast<MidiRegionView*> (rv);
+ if (mrv) {
+ list<pair<PBD::ID const, list<boost::shared_ptr<Evoral::Note<Evoral::Beats> > > > >::iterator rnote;
+ for (rnote = selection->pending_midi_note_selection.begin(); rnote != selection->pending_midi_note_selection.end(); ++rnote) {
+ if (rv->region()->id () == (*rnote).first) {
+ mrv->select_notes ((*rnote).second);
+ selection->pending_midi_note_selection.erase(rnote);
+ break;
+ }
+ }
+ }
+
_summary->set_background_dirty ();
}
RouteTimeAxisView *rtv;
list<RouteTimeAxisView*> new_views;
+ TrackViewList new_selection;
+ bool from_scratch = (track_views.size() == 0);
for (RouteList::iterator x = routes.begin(); x != routes.end(); ++x) {
boost::shared_ptr<Route> route = (*x);
new_views.push_back (rtv);
track_views.push_back (rtv);
+ new_selection.push_back (rtv);
rtv->effective_gain_display ();
_summary->routes_added (new_views);
}
+ if (!from_scratch) {
+ selection->tracks.clear();
+ selection->add (new_selection);
+ begin_selection_op_history();
+ }
+
if (show_editor_mixer_when_tracks_arrive) {
show_editor_mixer (true);
}