introduce the notion that note additions and property changes can cause the removal...
[ardour.git] / gtk2_ardour / editor_ops.cc
index b2174d1933053183da56ccc9cac1fb213818d674..9206f1516bfc1a2581d69237d028a346e5ec58d3 100644 (file)
@@ -79,6 +79,7 @@
 #include "editor_routes.h"
 #include "editor_regions.h"
 #include "quantize_dialog.h"
+#include "interthread_progress_window.h"
 
 #include "i18n.h"
 
@@ -155,7 +156,13 @@ Editor::split_regions_at (nframes64_t where, RegionSelection& regions)
 
                boost::shared_ptr<Playlist> pl = (*a)->region()->playlist();
 
-               if (! pl->frozen()) {
+                if (!pl) {
+                        cerr << "region " << (*a)->region()->name() << " has no playlist!\n";
+                        a = tmp;
+                        continue;
+                }
+
+               if (!pl->frozen()) {
                        /* we haven't seen this playlist before */
 
                        /* remember used playlists so we can thaw them later */
@@ -163,11 +170,6 @@ Editor::split_regions_at (nframes64_t where, RegionSelection& regions)
                        pl->freeze();
                }
 
-               AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*a);
-               if (arv) {
-                       _new_regionviews_show_envelope = arv->envelope_visible();
-               }
-
                if (pl) {
                         pl->clear_history ();
                        pl->split_region ((*a)->region(), where);
@@ -184,7 +186,6 @@ Editor::split_regions_at (nframes64_t where, RegionSelection& regions)
        }
 
        commit_reversible_command ();
-       _new_regionviews_show_envelope = false;
 }
 
 boost::shared_ptr<Region>
@@ -630,8 +631,8 @@ Editor::build_region_boundary_cache ()
                        RouteTimeAxisView *rtav;
 
                        if (ontrack != 0 && (rtav = dynamic_cast<RouteTimeAxisView*>(ontrack)) != 0 ) {
-                               if (rtav->get_diskstream() != 0) {
-                                       speed = rtav->get_diskstream()->speed();
+                               if (rtav->track() != 0) {
+                                       speed = rtav->track()->speed();
                                }
                        }
 
@@ -685,8 +686,8 @@ Editor::find_next_region (nframes64_t frame, RegionPoint point, int32_t dir, Tra
 
                track_speed = 1.0f;
                if ( (rtav = dynamic_cast<RouteTimeAxisView*>(*i)) != 0 ) {
-                       if (rtav->get_diskstream()!=0)
-                               track_speed = rtav->get_diskstream()->speed();
+                       if (rtav->track()!=0)
+                               track_speed = rtav->track()->speed();
                }
 
                track_frame = session_frame_to_track_frame(frame, track_speed);
@@ -886,8 +887,8 @@ Editor::cursor_to_region_point (EditorCursor* cursor, RegionPoint point, int32_t
        RouteTimeAxisView *rtav;
 
        if ( ontrack != 0 && (rtav = dynamic_cast<RouteTimeAxisView*>(ontrack)) != 0 ) {
-               if (rtav->get_diskstream() != 0) {
-                       speed = rtav->get_diskstream()->speed();
+               if (rtav->track() != 0) {
+                       speed = rtav->track()->speed();
                }
        }
 
@@ -1083,8 +1084,8 @@ Editor::selected_marker_to_region_point (RegionPoint point, int32_t dir)
        RouteTimeAxisView *rtav;
 
        if (ontrack != 0 && (rtav = dynamic_cast<RouteTimeAxisView*>(ontrack)) != 0) {
-               if (rtav->get_diskstream() != 0) {
-                       speed = rtav->get_diskstream()->speed();
+               if (rtav->track() != 0) {
+                       speed = rtav->track()->speed();
                }
        }
 
@@ -1549,7 +1550,7 @@ Editor::temporal_zoom (gdouble fpu)
 
        /* XXX this limit is also in ::set_frames_per_unit() */
 
-       if (frames_per_unit <= 2.0 && fpu <= frames_per_unit) {
+       if (frames_per_unit <= 1.0 && fpu <= frames_per_unit) {
                return;
        }
 
@@ -1735,7 +1736,7 @@ Editor::temporal_zoom_region (bool both_axes)
 
                for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
                        if (find (tracks.begin(), tracks.end(), (*i)) == tracks.end()) {
-                               hide_track_in_display (**i, true);
+                               hide_track_in_display (*i, true);
                        }
                }
 
@@ -1775,7 +1776,13 @@ Editor::temporal_zoom_session ()
        ENSURE_GUI_THREAD (*this, &Editor::temporal_zoom_session)
 
        if (_session) {
-               temporal_zoom_by_frame (_session->current_start_frame(), _session->current_end_frame(), "zoom to _session");
+               nframes_t const l = _session->current_end_frame() - _session->current_start_frame();
+               double s = _session->current_start_frame() - l * 0.01;
+               if (s < 0) {
+                       s = 0;
+               }
+               nframes_t const e = _session->current_end_frame() + l * 0.01;
+               temporal_zoom_by_frame (nframes_t (s), e, "zoom to _session");
        }
 }
 
@@ -2190,8 +2197,6 @@ Editor::insert_region_list_drag (boost::shared_ptr<Region> region, int x, int y)
        boost::shared_ptr<Playlist> playlist;
 
        track_canvas->window_to_world (x, y, wx, wy);
-       //wx += horizontal_adjustment.get_value();
-       //wy += vertical_adjustment.get_value();
 
        GdkEvent event;
        event.type = GDK_BUTTON_RELEASE;
@@ -2228,7 +2233,8 @@ Editor::insert_region_list_drag (boost::shared_ptr<Region> region, int x, int y)
 }
 
 void
-Editor::insert_route_list_drag (boost::shared_ptr<Route> route, int x, int y) {
+Editor::insert_route_list_drag (boost::shared_ptr<Route> route, int x, int y)
+{
        double wx, wy;
        double cx, cy;
        nframes_t where;
@@ -2236,7 +2242,7 @@ Editor::insert_route_list_drag (boost::shared_ptr<Route> route, int x, int y) {
        RouteTimeAxisView *source_rtv = 0;
 
        track_canvas->window_to_world (x, y, wx, wy);
-       wx += horizontal_adjustment.get_value();
+       wx += horizontal_position ();
        wy += vertical_adjustment.get_value();
 
        GdkEvent event;
@@ -2506,8 +2512,8 @@ Editor::rename_region()
        d.get_vbox()->set_border_width (12);
        d.get_vbox()->pack_start (hbox, false, false);
 
-       d.add_button(Gtk::Stock::OK, Gtk::RESPONSE_OK);
        d.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
+       d.add_button(Gtk::Stock::OK, Gtk::RESPONSE_OK);
 
        d.set_size_request (300, -1);
        d.set_position (Gtk::WIN_POS_MOUSE);
@@ -2596,39 +2602,6 @@ Editor::audition_playlist_region_standalone (boost::shared_ptr<Region> region)
        _session->audition_region (region);
 }
 
-void
-Editor::build_interthread_progress_window ()
-{
-       interthread_progress_window = new ArdourDialog (X_("interthread progress"), true);
-
-       interthread_progress_bar.set_orientation (Gtk::PROGRESS_LEFT_TO_RIGHT);
-
-       interthread_progress_window->set_border_width (12);
-       interthread_progress_window->get_vbox()->set_spacing (6);
-
-       interthread_progress_label.set_alignment (0.5, 0.5);
-
-       interthread_progress_window->get_vbox()->pack_start (interthread_progress_label, false, false);
-       interthread_progress_window->get_vbox()->pack_start (interthread_progress_bar,false, false);
-
-       // GTK2FIX: this button needs a modifiable label
-
-       Button* b = interthread_progress_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
-       b->signal_clicked().connect (sigc::mem_fun(*this, &Editor::interthread_cancel_clicked));
-
-       interthread_cancel_button.add (interthread_cancel_label);
-
-       interthread_progress_window->set_default_size (200, 100);
-}
-
-void
-Editor::interthread_cancel_clicked ()
-{
-       if (current_interthread_info) {
-               current_interthread_info->cancel = true;
-       }
-}
-
 void
 Editor::region_from_selection ()
 {
@@ -2662,7 +2635,7 @@ Editor::region_from_selection ()
                }
 
                internal_start = start - current->position();
-               _session->region_name (new_name, current->name(), true);
+               RegionFactory::region_name (new_name, current->name(), true);
 
                PropertyList plist; 
                
@@ -2702,7 +2675,7 @@ Editor::create_region_from_selection (vector<boost::shared_ptr<Region> >& new_re
                }
 
                internal_start = start - current->position();
-               _session->region_name (new_name, current->name(), true);
+               RegionFactory::region_name (new_name, current->name(), true);
 
                PropertyList plist; 
                
@@ -2808,7 +2781,7 @@ Editor::separate_regions_between (const TimeSelection& ts)
 
                                /* no edits to destructive tracks */
 
-                               if (rtv->track()->diskstream()->destructive()) {
+                               if (rtv->track()->destructive()) {
                                        continue;
                                }
 
@@ -2818,7 +2791,7 @@ Editor::separate_regions_between (const TimeSelection& ts)
 
                                        /* XXX need to consider musical time selections here at some point */
 
-                                       double speed = rtv->get_diskstream()->speed();
+                                       double speed = rtv->track()->speed();
 
 
                                        for (list<AudioRange>::const_iterator t = ts.begin(); t != ts.end(); ++t) {
@@ -2965,7 +2938,7 @@ Editor::crop_region_to (nframes64_t start, nframes64_t end)
 
                        boost::shared_ptr<Track> t = rtv->track();
 
-                       if (t != 0 && ! t->diskstream()->destructive()) {
+                       if (t != 0 && ! t->destructive()) {
 
                                if ((playlist = rtv->playlist()) != 0) {
                                        playlists.push_back (playlist);
@@ -3437,8 +3410,8 @@ Editor::trim_region_to_location (const Location& loc, const char* str)
                nframes64_t start;
                nframes64_t end;
 
-               if (tav->get_diskstream() != 0) {
-                       speed = tav->get_diskstream()->speed();
+               if (tav->track() != 0) {
+                       speed = tav->track()->speed();
                }
 
                start = session_frame_to_track_frame (loc.start(), speed);
@@ -3478,8 +3451,8 @@ Editor::trim_region_to_edit_point ()
 
                float speed = 1.0;
 
-               if (tav->get_diskstream() != 0) {
-                       speed = tav->get_diskstream()->speed();
+               if (tav->track() != 0) {
+                       speed = tav->track()->speed();
                }
 
                 rv->region()->clear_history ();
@@ -3516,8 +3489,8 @@ Editor::trim_region_from_edit_point ()
 
                float speed = 1.0;
 
-               if (tav->get_diskstream() != 0) {
-                       speed = tav->get_diskstream()->speed();
+               if (tav->track() != 0) {
+                       speed = tav->track()->speed();
                }
 
                 rv->region()->clear_history ();
@@ -3567,8 +3540,8 @@ Editor::trim_to_region(bool forward)
 
                float speed = 1.0;
 
-               if (atav->get_diskstream() != 0) {
-                       speed = atav->get_diskstream()->speed();
+               if (atav->track() != 0) {
+                       speed = atav->track()->speed();
                }
 
 
@@ -3633,13 +3606,6 @@ Editor::freeze_thread ()
        return 0;
 }
 
-gint
-Editor::freeze_progress_timeout (void */*arg*/)
-{
-       interthread_progress_bar.set_fraction (current_interthread_info->progress);
-       return !(current_interthread_info->done || current_interthread_info->cancel);
-}
-
 void
 Editor::freeze_route ()
 {
@@ -3648,25 +3614,9 @@ Editor::freeze_route ()
        }
 
        InterThreadInfo itt;
-
-       if (interthread_progress_window == 0) {
-               build_interthread_progress_window ();
-       }
-
-       interthread_progress_window->set_title (_("Freeze"));
-       interthread_progress_window->set_position (Gtk::WIN_POS_MOUSE);
-       interthread_progress_window->show_all ();
-       interthread_progress_bar.set_fraction (0.0f);
-       interthread_progress_label.set_text ("");
-       interthread_cancel_label.set_text (_("Cancel Freeze"));
        current_interthread_info = &itt;
 
-       interthread_progress_connection =
-         Glib::signal_timeout().connect (sigc::bind (sigc::mem_fun(*this, &Editor::freeze_progress_timeout), (gpointer) 0), 100);
-
-       itt.done = false;
-       itt.cancel = false;
-       itt.progress = 0.0f;
+       InterthreadProgressWindow ipw (current_interthread_info, _("Freeze"), _("Cancel Freeze"));
 
        pthread_create_and_store (X_("freezer"), &itt.thread, _freeze_thread, this);
 
@@ -3676,8 +3626,6 @@ Editor::freeze_route ()
                gtk_main_iteration ();
        }
 
-       interthread_progress_connection.disconnect ();
-       interthread_progress_window->hide_all ();
        current_interthread_info = 0;
        track_canvas->get_window()->set_cursor (*current_canvas_cursor);
 }
@@ -3713,11 +3661,9 @@ Editor::bounce_range_selection (bool replace, bool enable_processing)
 
                InterThreadInfo itt;
 
-               itt.done = false;
-               itt.cancel = false;
-               itt.progress = false;
-
                 playlist->clear_history ();
+               playlist->clear_owned_history ();
+               
                boost::shared_ptr<Region> r = rtv->track()->bounce_range (start, start+cnt, itt, enable_processing);
 
                if (replace) {
@@ -3727,7 +3673,13 @@ Editor::bounce_range_selection (bool replace, bool enable_processing)
                        playlist->add_region (r, start);
                }
 
-               _session->add_command (new StatefulDiffCommand (playlist));
+               vector<StatefulDiffCommand*> cmds;
+               playlist->rdiff (cmds);
+               for (vector<StatefulDiffCommand*>::iterator j = cmds.begin(); j != cmds.end(); ++j) {
+                       _session->add_command (*j);
+               }
+
+                _session->add_command (new StatefulDiffCommand (playlist));
        }
 
        commit_reversible_command ();
@@ -3821,7 +3773,7 @@ Editor::cut_copy (CutCopyOp op)
                        Glib::signal_idle().connect (sigc::bind (sigc::mem_fun(*this, &Editor::really_remove_marker), loc));
                }
 
-               _drags->break_drag ();
+               _drags->abort ();
                return;
        }
 
@@ -3902,7 +3854,7 @@ Editor::cut_copy (CutCopyOp op)
        }
 
        if (op == Cut || op == Clear) {
-               _drags->break_drag ();
+               _drags->abort ();
        }
 }
 
@@ -3934,17 +3886,6 @@ Editor::cut_copy_midi (CutCopyOp op)
        }
 }
 
-struct PlaylistState {
-    boost::shared_ptr<Playlist> playlist;
-    XMLNode*  before;
-};
-
-struct lt_playlist {
-    bool operator () (const PlaylistState& a, const PlaylistState& b) {
-           return a.playlist < b.playlist;
-    }
-};
-
 struct PlaylistMapping {
     TimeAxisView* tv;
     boost::shared_ptr<Playlist> pl;
@@ -4057,8 +3998,8 @@ Editor::cut_copy_regions (CutCopyOp op, RegionSelection& rs)
 
        nframes64_t first_position = max_frames;
 
-       set<PlaylistState, lt_playlist> freezelist;
-       pair<set<PlaylistState, lt_playlist>::iterator,bool> insert_result;
+       typedef set<boost::shared_ptr<Playlist> > FreezeList;
+        FreezeList freezelist;
 
        /* get ordering correct before we cut/copy */
 
@@ -4072,21 +4013,19 @@ Editor::cut_copy_regions (CutCopyOp op, RegionSelection& rs)
                        boost::shared_ptr<Playlist> pl = (*x)->region()->playlist();
 
                        if (pl) {
-                               set<PlaylistState, lt_playlist>::iterator fl;
+                               FreezeList::iterator fl;
 
                                //only take state if this is a new playlist.
                                for (fl = freezelist.begin(); fl != freezelist.end(); ++fl) {
-                                       if ((*fl).playlist == pl) {
+                                       if ((*fl) == pl) {
                                                break;
                                        }
                                }
 
                                if (fl == freezelist.end()) {
-                                       PlaylistState before;
-                                       before.playlist = pl;
-                                       before.before = &pl->get_state();
+                                        pl->clear_history();
                                        pl->freeze ();
-                                       insert_result = freezelist.insert (before);
+                                       freezelist.insert (pl);
                                }
                        }
                }
@@ -4177,10 +4116,10 @@ Editor::cut_copy_regions (CutCopyOp op, RegionSelection& rs)
        if (!foo.empty()) {
                cut_buffer->set (foo);
        }
-
-       for (set<PlaylistState, lt_playlist>::iterator pl = freezelist.begin(); pl != freezelist.end(); ++pl) {
-               (*pl).playlist->thaw ();
-               _session->add_command (new MementoCommand<Playlist>(*(*pl).playlist, (*pl).before, &(*pl).playlist->get_state()));
+        
+       for (FreezeList::iterator pl = freezelist.begin(); pl != freezelist.end(); ++pl) {
+               (*pl)->thaw ();
+               _session->add_command (new StatefulDiffCommand (*pl));
        }
 }
 
@@ -4440,13 +4379,20 @@ Editor::nudge_track (bool use_edit, bool forwards)
                        continue;
                }
 
-                /* XXX STATEFUL this won't capture region moves if don't as a stateful diff
-                 */
+                playlist->clear_history ();
+                playlist->clear_owned_history ();
 
-                XMLNode &before = playlist->get_state();
                playlist->nudge_after (start, distance, forwards);
-                XMLNode &after = playlist->get_state();
-               _session->add_command (new MementoCommand<Playlist>(*playlist, &before, &after));
+                
+                vector<StatefulDiffCommand*> cmds;
+
+                playlist->rdiff (cmds);
+
+                for (vector<StatefulDiffCommand*>::iterator c = cmds.begin(); c != cmds.end(); ++c) {
+                        _session->add_command (*c);
+                }
+
+                _session->add_command (new StatefulDiffCommand (playlist));
        }
 
        commit_reversible_command ();
@@ -4496,6 +4442,8 @@ Editor::normalize_region ()
 
        Dialog dialog (rs.size() > 1 ? _("Normalize regions") : _("Normalize region"));
        HBox hbox;
+       hbox.set_spacing (6);
+       hbox.set_border_width (6);
        hbox.pack_start (*manage (new Label (_("Normalize to:"))));
        SpinButton spin (0.2, 2);
        spin.set_range (-112, 0);
@@ -4505,6 +4453,7 @@ Editor::normalize_region ()
        spin.set_value (_last_normalization_value);
        hbox.pack_start (*manage (new Label (_("dbFS"))));
        hbox.show_all ();
+       dialog.get_vbox()->set_spacing (12);
        dialog.get_vbox()->pack_start (hbox);
        dialog.add_button (Stock::CANCEL, RESPONSE_CANCEL);
        dialog.add_button (_("Normalize"), RESPONSE_ACCEPT);
@@ -4651,7 +4600,7 @@ Editor::strip_region_silence ()
                }
        }
 
-       StripSilenceDialog d (ar);
+       StripSilenceDialog d (_session, ar);
        int const r = d.run ();
 
        if (r == Gtk::RESPONSE_OK) {
@@ -4664,7 +4613,7 @@ Command*
 Editor::apply_midi_note_edit_op_to_region (MidiOperator& op, MidiRegionView& mrv)
 {
        Evoral::Sequence<Evoral::MusicalTime>::Notes selected;
-       mrv.selection_as_notelist (selected);
+       mrv.selection_as_notelist (selected, true);
 
        vector<Evoral::Sequence<Evoral::MusicalTime>::Notes> v;
        v.push_back (selected);
@@ -4707,6 +4656,47 @@ Editor::apply_midi_note_edit_op (MidiOperator& op)
        rs.clear ();
 }
 
+void
+Editor::fork_region ()
+{
+       RegionSelection rs;
+
+       get_regions_for_action (rs);
+
+       if (rs.empty()) {
+               return;
+       }
+
+       begin_reversible_command (_("Fork Region(s)"));
+
+       track_canvas->get_window()->set_cursor (*wait_cursor);
+       gdk_flush ();
+
+       for (RegionSelection::iterator r = rs.begin(); r != rs.end(); ) {
+               RegionSelection::iterator tmp = r;
+               ++tmp;
+
+               MidiRegionView* const mrv = dynamic_cast<MidiRegionView*>(*r);
+
+               if (mrv) {
+                       boost::shared_ptr<Playlist> playlist = mrv->region()->playlist();
+                        boost::shared_ptr<MidiRegion> newregion = mrv->midi_region()->clone ();
+                        
+                        playlist->clear_history ();
+                        cerr << "Replace region with " << newregion->name() << endl;
+                        playlist->replace_region (mrv->region(), newregion, mrv->region()->position());
+                        _session->add_command(new StatefulDiffCommand (playlist));
+               }
+
+               r = tmp;
+       }
+
+       commit_reversible_command ();
+       rs.clear ();
+
+       track_canvas->get_window()->set_cursor (*current_canvas_cursor);
+}
+
 void
 Editor::quantize_region ()
 {
@@ -4940,7 +4930,7 @@ Editor::toggle_region_lock ()
 }
 
 void
-Editor::set_region_lock_style (Region::PositionLockStyle ps)
+Editor::toggle_region_lock_style ()
 {
        RegionSelection rs = get_equivalent_regions (selection->regions, ARDOUR::Properties::edit.property_id);
 
@@ -4952,7 +4942,8 @@ Editor::set_region_lock_style (Region::PositionLockStyle ps)
 
        for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
                 (*i)->region()->clear_history ();
-               (*i)->region()->set_position_lock_style (ps);
+               Region::PositionLockStyle const ns = (*i)->region()->positional_lock_style() == Region::AudioTime ? Region::MusicTime : Region::AudioTime;
+               (*i)->region()->set_position_lock_style (ns);
                _session->add_command (new StatefulDiffCommand ((*i)->region()));
        }
 
@@ -5039,7 +5030,7 @@ Editor::set_fade_length (bool in)
 
        nframes64_t pos = get_preferred_edit_position();
        nframes64_t len;
-       char* cmd;
+       char const * cmd;
 
        if (pos > rv->region()->last_frame() || pos < rv->region()->first_frame()) {
                /* edit point is outside the relevant region */
@@ -5927,7 +5918,7 @@ Editor::split_region_at_points (boost::shared_ptr<Region> r, AnalysisFeatureList
 
                string new_name;
 
-               if (_session->region_name (new_name, r->name())) {
+               if (RegionFactory::region_name (new_name, r->name())) {
                        break;
                }
 
@@ -5990,9 +5981,9 @@ Editor::tab_to_transient (bool forward)
                        RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*t);
 
                        if (rtv) {
-                               boost::shared_ptr<Diskstream> ds = rtv->get_diskstream();
-                               if (ds) {
-                                       boost::shared_ptr<Playlist> pl = rtv->get_diskstream()->playlist ();
+                               boost::shared_ptr<Track> tr = rtv->track();
+                               if (tr) {
+                                       boost::shared_ptr<Playlist> pl = tr->playlist ();
                                        if (pl) {
                                                nframes64_t result = pl->find_next_transient (pos, forward ? 1 : -1);
 
@@ -6074,7 +6065,7 @@ Editor::playhead_backward_to_grid ()
 }
 
 void
-Editor::set_track_height (uint32_t h)
+Editor::set_track_height (Height h)
 {
        TrackSelection& ts (selection->tracks);
 
@@ -6255,7 +6246,8 @@ Editor::do_insert_time ()
                return;
        }
 
-       InsertTimeOption opt;
+       /* only setting this to keep GCC quiet */
+       InsertTimeOption opt = LeaveIntersected;
 
        switch (intersected_combo.get_active_row_number ()) {
        case 0:
@@ -6290,10 +6282,8 @@ Editor::insert_time (nframes64_t pos, nframes64_t frames, InsertTimeOption opt,
 
                if (pl) {
 
-                        /* XXX STATEFUL this won't capture region motion if done as stateful diff 
-                         */
-
-                       XMLNode &before = pl->get_state();
+                       pl->clear_history ();
+                        pl->clear_owned_history ();
 
                        if (opt == SplitIntersected) {
                                pl->split (pos);
@@ -6301,9 +6291,17 @@ Editor::insert_time (nframes64_t pos, nframes64_t frames, InsertTimeOption opt,
 
                        pl->shift (pos, frames, (opt == MoveIntersected), ignore_music_glue);
 
-                       XMLNode &after = pl->get_state();
+                        vector<StatefulDiffCommand*> cmds;
+                        
+                        pl->rdiff (cmds);
+                        
+                        cerr << "Shift generated " << cmds.size() << " sdc's\n";
 
-                       _session->add_command (new MementoCommand<Playlist> (*pl, &before, &after));
+                        for (vector<StatefulDiffCommand*>::iterator c = cmds.begin(); c != cmds.end(); ++c) {
+                                _session->add_command (*c);
+                        }
+                        
+                       _session->add_command (new StatefulDiffCommand (pl));
                        commit = true;
                }
 
@@ -6376,7 +6374,7 @@ Editor::fit_tracks (TrackViewList & tracks)
        uint32_t h = (uint32_t) floor ((_canvas_height - child_heights - canvas_timebars_vsize) / tracks.size());
        double first_y_pos = DBL_MAX;
 
-       if (h < TimeAxisView::hSmall) {
+       if (h < TimeAxisView::preset_height (HeightSmall)) {
                MessageDialog msg (*this, _("There are too many tracks to fit in the current window"));
                /* too small to be displayed */
                return;
@@ -6408,7 +6406,7 @@ Editor::fit_tracks (TrackViewList & tracks)
                        first_y_pos = std::min ((*t)->y_position (), first_y_pos);
                } else {
                        if (prev_was_selected && next_is_selected) {
-                               hide_track_in_display (**t);
+                               hide_track_in_display (*t);
                        }
                }