Added support for exporting mp4 chapter marks
[ardour.git] / gtk2_ardour / editor.cc
index b18d6d6fb81fd17396a53f8c7eb112aff6e9c1f6..b1a1d7c4c6c5fee35ae0f309430457848a15151f 100644 (file)
@@ -68,6 +68,7 @@
 #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"
@@ -403,7 +404,7 @@ Editor::Editor ()
        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;
 
@@ -1795,7 +1796,7 @@ Editor::add_region_context_items (Menu_Helpers::MenuList& edit_items, boost::sha
                _popup_region_menu_item->set_label (menu_item_name);
        }
 
-       const framepos_t position = get_preferred_edit_position (false, true);
+       const framepos_t position = get_preferred_edit_position (EDIT_IGNORE_NONE, true);
 
        edit_items.push_back (*_popup_region_menu_item);
        if (track->playlist()->count_regions_at (position) > 1 && (layering_order_editor == 0 || !layering_order_editor->is_visible ())) {
@@ -1878,7 +1879,7 @@ Editor::add_selection_context_items (Menu_Helpers::MenuList& edit_items)
        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)));
        }
 }
 
@@ -2321,37 +2322,16 @@ Editor::set_state (const XMLNode& node, int /*version*/)
        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"))) {
@@ -2427,6 +2407,42 @@ Editor::set_state (const XMLNode& node, int /*version*/)
                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;
 }
 
@@ -3326,7 +3342,12 @@ Editor::begin_selection_op_history ()
 {
        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 ());
@@ -3336,7 +3357,7 @@ void
 Editor::begin_reversible_selection_op (string name)
 {
        if (_session) {
-               cerr << name << endl;
+               //cerr << name << endl;
                /* begin/commit pairs can be nested */
                selection_op_cmd_depth++;
        }
@@ -3349,10 +3370,19 @@ Editor::commit_reversible_selection_op ()
                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 */
+                               /**
+                                   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 ());
@@ -3428,12 +3458,25 @@ Editor::begin_reversible_command (GQuark q)
        }
 }
 
+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 ();
                }
@@ -3660,7 +3703,7 @@ Editor::build_track_count_menu ()
                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)));
@@ -3672,7 +3715,7 @@ Editor::build_track_count_menu ()
                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)));
@@ -3742,7 +3785,7 @@ Editor::set_visible_track_count (int32_t n)
        }
 
        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()) {
@@ -4434,6 +4477,7 @@ Editor::use_visual_state (VisualState& vs)
                *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 ();
                }
        }
@@ -4611,15 +4655,15 @@ Editor::sort_track_selection (TrackViewList& sel)
 }
 
 framepos_t
-Editor::get_preferred_edit_position (bool ignore_playhead, bool from_context_menu, bool from_outside_canvas)
+Editor::get_preferred_edit_position (EditIgnoreOption ignore, bool from_context_menu, bool from_outside_canvas)
 {
        bool ignored;
        framepos_t where = 0;
        EditPoint ep = _edit_point;
 
-       if(Profile->get_mixbus())
+       if (Profile->get_mixbus())
                if (ep == EditAtSelectedMarker)
-                       ep=EditAtPlayhead;
+                       ep = EditAtPlayhead;
 
        if (from_outside_canvas && (ep == EditAtMouse)) {
                ep = EditAtPlayhead;
@@ -4632,10 +4676,14 @@ Editor::get_preferred_edit_position (bool ignore_playhead, bool from_context_men
                return entered_marker->position();
        }
 
-       if (ignore_playhead && ep == EditAtPlayhead) {
+       if ( (ignore==EDIT_IGNORE_PHEAD) && ep == EditAtPlayhead) {
                ep = EditAtSelectedMarker;
        }
 
+       if ( (ignore==EDIT_IGNORE_MOUSE) && ep == EditAtMouse) {
+               ep = EditAtPlayhead;
+       }
+
        switch (ep) {
        case EditAtPlayhead:
                if (_dragging_playhead) {
@@ -4643,8 +4691,9 @@ Editor::get_preferred_edit_position (bool ignore_playhead, bool from_context_men
                                /* XXX not right but what can we do ? */
                                return 0;
                        }
-               } else
+               } else {
                        where = _session->audible_frame();
+               }
                 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use playhead @ %1\n", where));
                break;
 
@@ -4933,7 +4982,7 @@ Editor::get_per_region_note_selection (list<pair<PBD::ID, set<boost::shared_ptr<
 
        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);
@@ -5193,6 +5242,8 @@ Editor::add_routes (RouteList& routes)
 
        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);
@@ -5215,6 +5266,7 @@ Editor::add_routes (RouteList& routes)
 
                new_views.push_back (rtv);
                track_views.push_back (rtv);
+               new_selection.push_back (rtv);
 
                rtv->effective_gain_display ();
 
@@ -5227,6 +5279,12 @@ Editor::add_routes (RouteList& routes)
                _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);
        }
@@ -5719,7 +5777,7 @@ Editor::show_editor_list (bool yn)
 void
 Editor::change_region_layering_order (bool from_context_menu)
 {
-       const framepos_t position = get_preferred_edit_position (false, from_context_menu);
+       const framepos_t position = get_preferred_edit_position (EDIT_IGNORE_NONE, from_context_menu);
 
        if (!clicked_routeview) {
                if (layering_order_editor) {