Better method for redrawing gain meter pixmaps upon theme change
[ardour.git] / gtk2_ardour / editor_mouse.cc
index 1a9e1161c283d3c16367349f5a2c4e4e06ef0644..457022874285c101b845ef5aa1c6eb1089c986e6 100644 (file)
@@ -34,6 +34,7 @@
 #include "time_axis_view.h"
 #include "audio_time_axis.h"
 #include "audio_region_view.h"
+#include "midi_region_view.h"
 #include "marker.h"
 #include "streamview.h"
 #include "region_gain_line.h"
@@ -53,6 +54,7 @@
 #include <ardour/playlist.h>
 #include <ardour/audioplaylist.h>
 #include <ardour/audioregion.h>
+#include <ardour/midi_region.h>
 #include <ardour/dB.h>
 #include <ardour/utils.h>
 #include <ardour/region_factory.h>
@@ -328,22 +330,8 @@ Editor::button_selection (ArdourCanvas::Item* item, GdkEvent* event, ItemType it
        
        switch (item_type) {
        case RegionItem:
-               if (mouse_mode != MouseRange) {
-                       commit = set_selected_regionview_from_click (press, op, true);
-               } else if (event->type == GDK_BUTTON_PRESS) {
-                       commit = set_selected_track_from_click (press, op, false);
-               }
-               break;
-               
        case RegionViewNameHighlight:
        case RegionViewName:
-               if (mouse_mode != MouseRange) {
-                       commit = set_selected_regionview_from_click (press, op, true);
-               } else if (event->type == GDK_BUTTON_PRESS) {
-                       commit = set_selected_track_from_click (press, op, false);
-               }
-               break;
-
        case FadeInHandleItem:
        case FadeInItem:
        case FadeOutHandleItem:
@@ -354,7 +342,11 @@ Editor::button_selection (ArdourCanvas::Item* item, GdkEvent* event, ItemType it
                        commit = set_selected_track_from_click (press, op, false);
                }
                break;
-               
+
+       case CrossfadeViewItem:
+               commit = set_selected_track_from_click (press, op, false);
+               break;
+                       
        case GainAutomationControlPointItem:
        case PanAutomationControlPointItem:
        case RedirectAutomationControlPointItem:
@@ -563,7 +555,7 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp
                                        start_rubberband_select (item, event);
                                        break;
                                        
-                               /* <CMT Additions> */
+#ifdef WITH_CMT
                                case ImageFrameHandleStartItem:
                                        imageframe_start_handle_op(item, event) ;
                                        return(true) ;
@@ -580,16 +572,13 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp
                                        markerview_item_end_handle_op(item, event) ;
                                        return(true) ;
                                        break ;
-                               /* </CMT Additions> */
-                               
-                               /* <CMT Additions> */
                                case MarkerViewItem:
                                        start_markerview_grab(item, event) ;
                                        break ;
                                case ImageFrameItem:
                                        start_imageframe_grab(item, event) ;
                                        break ;
-                               /* </CMT Additions> */
+#endif
 
                                case MarkerBarItem:
                                        
@@ -823,21 +812,13 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
                                break;
 
                        case StreamItem:
-                               popup_track_context_menu (1, event->button.time, item_type, false, where);
-                               break;
-                               
                        case RegionItem:
                        case RegionViewNameHighlight:
                        case RegionViewName:
-                               popup_track_context_menu (1, event->button.time, item_type, false, where);
-                               break;
-                               
                        case SelectionItem:
-                               popup_track_context_menu (1, event->button.time, item_type, true, where);
-                               break;
-
                        case AutomationTrackItem:
-                               popup_track_context_menu (1, event->button.time, item_type, false, where);
+                       case CrossfadeViewItem:
+                               popup_track_context_menu (1, event->button.time, where);
                                break;
 
                        case MarkerBarItem: 
@@ -860,11 +841,7 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
                                tm_marker_context_menu (&event->button, item);
                                break;
 
-                       case CrossfadeViewItem:
-                               popup_track_context_menu (1, event->button.time, item_type, false, where);
-                               break;
-
-                       /* <CMT Additions> */
+#ifdef WITH_CMT
                        case ImageFrameItem:
                                popup_imageframe_edit_menu(1, event->button.time, item, true) ;
                                break ;
@@ -877,8 +854,7 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
                        case MarkerTimeAxisItem:
                                popup_marker_time_axis_edit_menu(1, event->button.time, item, false) ;
                                break ;
-                       /* <CMT Additions> */
-
+#endif
                                
                        default:
                                break;
@@ -972,7 +948,7 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
                case MouseObject:
                        switch (item_type) {
                        case AutomationTrackItem:
-                               dynamic_cast<AutomationTimeAxisView*>(clicked_trackview)->add_automation_event 
+                               dynamic_cast<AutomationTimeAxisView*>(clicked_axisview)->add_automation_event 
                                        (item,
                                         event,
                                         where,
@@ -999,7 +975,7 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
                                break;
                                
                        case AutomationTrackItem:
-                               dynamic_cast<AutomationTimeAxisView*>(clicked_trackview)->
+                               dynamic_cast<AutomationTimeAxisView*>(clicked_axisview)->
                                        add_automation_event (item, event, where, event->button.y);
                                return true;
                                break;
@@ -1030,25 +1006,6 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
        case 2:
                switch (mouse_mode) {
                        
-               case MouseObject:
-                       switch (item_type) {
-                       case RegionItem:
-                               if (Keyboard::modifier_state_equals (event->button.state, Keyboard::Shift)) {
-                                       raise_region ();
-                               } else if (Keyboard::modifier_state_equals (event->button.state, Keyboard::ModifierMask (Keyboard::Shift|Keyboard::Alt))) {
-                                       lower_region ();
-                               } else {
-                                       // Button2 click is unused
-                               }
-                               return true;
-                               
-                               break;
-                               
-                       default:
-                               break;
-                       }
-                       break;
-                       
                case MouseRange:
                        
                        // x_style_paste (where, 1.0);
@@ -1090,7 +1047,7 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_
                        at_x += 20.0;
                        at_y += 20.0;
 
-                       fraction = 1.0 - (cp->get_y() / cp->line.height());
+                       fraction = 1.0 - ((cp->get_y() - cp->line.y_position()) / cp->line.height());
 
                        set_verbose_canvas_cursor (cp->line.get_verbose_cursor_string (fraction), at_x, at_y);
                        show_verbose_canvas_cursor ();
@@ -1160,12 +1117,13 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_
 
        case StartSelectionTrimItem:
        case EndSelectionTrimItem:
-       /* <CMT Additions> */
+
+#ifdef WITH_CMT
        case ImageFrameHandleStartItem:
        case ImageFrameHandleEndItem:
        case MarkerViewHandleStartItem:
        case MarkerViewHandleEndItem:
-       /* </CMT Additions> */
+#endif
 
                if (is_drawable()) {
                        track_canvas.get_window()->set_cursor (*trimmer_cursor);
@@ -1315,12 +1273,14 @@ Editor::leave_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_
        case EndSelectionTrimItem:
        case EditCursorItem:
        case PlayheadCursorItem:
-       /* <CMT Additions> */
+
+#ifdef WITH_CMT
        case ImageFrameHandleStartItem:
        case ImageFrameHandleEndItem:
        case MarkerViewHandleStartItem:
        case MarkerViewHandleEndItem:
-       /* </CMT Additions> */
+#endif
+
                if (is_drawable()) {
                        track_canvas.get_window()->set_cursor (*current_canvas_cursor);
                }
@@ -1486,12 +1446,14 @@ Editor::motion_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item
        case PanAutomationLineItem:
        case FadeInHandleItem:
        case FadeOutHandleItem:
-       /* <CMT Additions> */
+
+#ifdef WITH_CMT
        case ImageFrameHandleStartItem:
        case ImageFrameHandleEndItem:
        case MarkerViewHandleStartItem:
        case MarkerViewHandleEndItem:
-       /* </CMT Additions> */
+#endif
+
          if (drag_info.item && (event->motion.state & Gdk::BUTTON1_MASK ||
                                 (event->motion.state & Gdk::BUTTON2_MASK))) {
                  if (!from_autoscroll) {
@@ -1620,7 +1582,6 @@ Editor::end_grab (ArdourCanvas::Item* item, GdkEvent* event)
        stop_canvas_autoscroll ();
 
        if (drag_info.item == 0) {
-               cerr << "end grab with no item\n";
                return false;
        }
        
@@ -2466,7 +2427,7 @@ void
 Editor::start_control_point_grab (ArdourCanvas::Item* item, GdkEvent* event)
 {
        ControlPoint* control_point;
-       
+
        if ((control_point = reinterpret_cast<ControlPoint *> (item->get_data ("control_point"))) == 0) {
                fatal << _("programming error: control point canvas item has no control point object pointer!") << endmsg;
                /*NOTREACHED*/
@@ -2481,7 +2442,7 @@ Editor::start_control_point_grab (ArdourCanvas::Item* item, GdkEvent* event)
 
        control_point->line.start_drag (control_point, drag_info.grab_frame, 0);
 
-       float fraction = 1.0 - (control_point->get_y() / control_point->line.height());
+       float fraction = 1.0 - ((control_point->get_y() - control_point->line.y_position()) / control_point->line.height());
        set_verbose_canvas_cursor (control_point->line.get_verbose_cursor_string (fraction), 
                                   drag_info.current_pointer_x + 20, drag_info.current_pointer_y + 20);
 
@@ -2510,7 +2471,7 @@ Editor::control_point_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent*
 
        cx = max (0.0, cx);
        cy = max (0.0, cy);
-       cy = min ((double) cp->line.height(), cy);
+       cy = min ((double) (cp->line.y_position() + cp->line.height()), cy);
 
        //translate cx to frames
        nframes_t cx_frames = unit_to_frame (cx);
@@ -2519,8 +2480,8 @@ Editor::control_point_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent*
                snap_to (cx_frames);
        }
 
-       float fraction = 1.0 - (cy / cp->line.height());
-       
+       float const fraction = 1.0 - ((cy - cp->line.y_position()) / cp->line.height());
+
        bool push;
 
        if (Keyboard::modifier_state_contains (event->button.state, Keyboard::Control)) {
@@ -2610,7 +2571,7 @@ Editor::start_line_grab (AutomationLine* line, GdkEvent* event)
 
        start_grab (event, fader_cursor);
 
-       double fraction = 1.0 - (cy / line->height());
+       double const fraction = 1.0 - ((cy - line->y_position()) / line->height());
 
        line->start_drag (0, drag_info.grab_frame, fraction);
        
@@ -2628,8 +2589,7 @@ Editor::line_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
 
        line->parent_group().w2i (cx, cy);
        
-       double fraction;
-       fraction = 1.0 - (cy / line->height());
+       double const fraction = 1.0 - ((cy - line->y_position()) / line->height());
 
        bool push;
 
@@ -2668,10 +2628,10 @@ Editor::start_region_grab (ArdourCanvas::Item* item, GdkEvent* event)
        start_grab (event);
 
        double speed = 1.0;
-       TimeAxisView* tvp = clicked_trackview;
+       TimeAxisView* tvp = clicked_axisview;
        RouteTimeAxisView* tv = dynamic_cast<RouteTimeAxisView*>(tvp);
 
-       if (tv && tv->is_audio_track()) {
+       if (tv && tv->is_track()) {
                speed = tv->get_diskstream()->speed();
        }
        
@@ -2700,11 +2660,11 @@ Editor::start_region_copy_grab (ArdourCanvas::Item* item, GdkEvent* event)
        start_grab(event);
 
        TimeAxisView* tv = &clicked_regionview->get_time_axis_view();
-       RouteTimeAxisView* atv = dynamic_cast<RouteTimeAxisView*>(tv);
+       RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(tv);
        double speed = 1.0;
 
-       if (atv && atv->is_audio_track()) {
-               speed = atv->get_diskstream()->speed();
+       if (rtv && rtv->is_track()) {
+               speed = rtv->get_diskstream()->speed();
        }
        
        drag_info.last_trackview = &clicked_regionview->get_time_axis_view();
@@ -2733,10 +2693,10 @@ Editor::start_region_brush_grab (ArdourCanvas::Item* item, GdkEvent* event)
        start_grab (event);
 
        double speed = 1.0;
-       TimeAxisView* tvp = clicked_trackview;
+       TimeAxisView* tvp = clicked_axisview;
        RouteTimeAxisView* tv = dynamic_cast<RouteTimeAxisView*>(tvp);
 
-       if (tv && tv->is_audio_track()) {
+       if (tv && tv->is_track()) {
                speed = tv->get_diskstream()->speed();
        }
        
@@ -2768,23 +2728,26 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
                drag_info.want_move_threshold = false; // don't copy again
 
                /* duplicate the region(s) */
-               
+
                vector<RegionView*> new_regionviews;
                
                for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i) {
                        RegionView* rv;
                        RegionView* nrv;
-                       AudioRegionView* arv;
 
                        rv = (*i);
 
-                       
-                       if ((arv = dynamic_cast<AudioRegionView*>(rv)) == 0) {
-                               /* XXX handle MIDI here */
+                       AudioRegionView* arv = dynamic_cast<AudioRegionView*>(rv);
+                       MidiRegionView* mrv = dynamic_cast<MidiRegionView*>(rv);
+
+                       if (arv) {
+                               nrv = new AudioRegionView (*arv);
+                       } else if (mrv) {
+                               nrv = new MidiRegionView (*mrv);
+                       } else {
                                continue;
                        }
 
-                       nrv = new AudioRegionView (*arv);
                        nrv->get_canvas_group()->show ();
 
                        new_regionviews.push_back (nrv);
@@ -2801,22 +2764,22 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
                /* reset drag_info data to reflect the fact that we are dragging the copies */
                
                drag_info.data = new_regionviews.front();
-               
+
                swap_grab (new_regionviews.front()->get_canvas_group (), 0, event->motion.time);
        }
 
        /* Which trackview is this ? */
 
        TimeAxisView* tvp = trackview_by_y_position (drag_info.current_pointer_y);
-       AudioTimeAxisView* tv = dynamic_cast<AudioTimeAxisView*>(tvp);
+       RouteTimeAxisView* tv = dynamic_cast<RouteTimeAxisView*>(tvp);
 
        /* The region motion is only processed if the pointer is over
           an audio track.
        */
        
-       if (!tv || !tv->is_audio_track()) {
+       if (!tv || !tv->is_track()) {
                /* To make sure we hide the verbose canvas cursor when the mouse is 
-                  not held over and audiotrack. 
+                  not held over a track. 
                */
                hide_verbose_canvas_cursor ();
                return;
@@ -2844,30 +2807,30 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
                for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
                        TimeAxisView *tracklist_timeview;
                        tracklist_timeview = (*i);
-                       AudioTimeAxisView* atv2 = dynamic_cast<AudioTimeAxisView*>(tracklist_timeview);
+                       RouteTimeAxisView* rtv2 = dynamic_cast<RouteTimeAxisView*>(tracklist_timeview);
                        list<TimeAxisView*> children_list;
              
                        /* zeroes are audio tracks. ones are other types. */
              
-                       if (!atv2->hidden()) {
+                       if (!rtv2->hidden()) {
                                
-                               if (visible_y_high < atv2->order) {
-                                       visible_y_high = atv2->order;
+                               if (visible_y_high < rtv2->order) {
+                                       visible_y_high = rtv2->order;
                                }
-                               if (visible_y_low > atv2->order) {
-                                       visible_y_low = atv2->order;
+                               if (visible_y_low > rtv2->order) {
+                                       visible_y_low = rtv2->order;
                                }
                
-                               if (!atv2->is_audio_track()) {                            
-                                       tracks = tracks |= (0x01 << atv2->order);
+                               if (!rtv2->is_track()) {                                  
+                                       tracks = tracks |= (0x01 << rtv2->order);
                                }
        
-                               height_list[atv2->order] = (*i)->height;
+                               height_list[rtv2->order] = (*i)->height;
                                children = 1;
-                               if ((children_list = atv2->get_child_list()).size() > 0) {
+                               if ((children_list = rtv2->get_child_list()).size() > 0) {
                                        for (list<TimeAxisView*>::iterator j = children_list.begin(); j != children_list.end(); ++j) { 
-                                               tracks = tracks |= (0x01 << (atv2->order + children));
-                                               height_list[atv2->order + children] =  (*j)->height;                
+                                               tracks = tracks |= (0x01 << (rtv2->order + children));
+                                               height_list[rtv2->order + children] =  (*j)->height;                
                                                numtracks++;
                                                children++;     
                                        }
@@ -2902,27 +2865,27 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
                        rv2->get_canvas_frame()->get_bounds (ix1, iy1, ix2, iy2);
                        rv2->get_canvas_group()->i2w (ix1, iy1);
                        TimeAxisView* tvp2 = trackview_by_y_position (iy1);
-                       RouteTimeAxisView* atv2 = dynamic_cast<RouteTimeAxisView*>(tvp2);
+                       RouteTimeAxisView* rtv2 = dynamic_cast<RouteTimeAxisView*>(tvp2);
 
-                       if (atv2->order != original_pointer_order) {    
+                       if (rtv2->order != original_pointer_order) {    
                                /* this isn't the pointer track */      
 
                                if (canvas_pointer_y_span > 0) {
 
                                        /* moving up the canvas */
-                                       if ((atv2->order - canvas_pointer_y_span) >= visible_y_low) {
+                                       if ((rtv2->order - canvas_pointer_y_span) >= visible_y_low) {
        
                                                int32_t visible_tracks = 0;
                                                while (visible_tracks < canvas_pointer_y_span ) {
                                                        visible_tracks++;
                  
-                                                       while (height_list[atv2->order - (visible_tracks - n)] == 0) {
+                                                       while (height_list[rtv2->order - (visible_tracks - n)] == 0) {
                                                                /* we're passing through a hidden track */
                                                                n--;
                                                        }                 
                                                }
                 
-                                               if (tracks[atv2->order - (canvas_pointer_y_span - n)] != 0x00) {                  
+                                               if (tracks[rtv2->order - (canvas_pointer_y_span - n)] != 0x00) {                  
                                                        clamp_y_axis = true;
                                                }
                    
@@ -2934,7 +2897,7 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
 
                                        /*moving down the canvas*/
 
-                                       if ((atv2->order - (canvas_pointer_y_span - n)) <= visible_y_high) { // we will overflow
+                                       if ((rtv2->order - (canvas_pointer_y_span - n)) <= visible_y_high) { // we will overflow
                    
                    
                                                int32_t visible_tracks = 0;
@@ -2942,11 +2905,11 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
                                                while (visible_tracks > canvas_pointer_y_span ) {
                                                        visible_tracks--;
                      
-                                                       while (height_list[atv2->order - (visible_tracks - n)] == 0) {             
+                                                       while (height_list[rtv2->order - (visible_tracks - n)] == 0) {             
                                                                n++;
                                                        }                
                                                }
-                                               if (  tracks[atv2->order - ( canvas_pointer_y_span - n)] != 0x00) {
+                                               if (  tracks[rtv2->order - ( canvas_pointer_y_span - n)] != 0x00) {
                                                        clamp_y_axis = true;
                            
                                                }
@@ -2959,9 +2922,9 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
                        } else {
                      
                                /* this is the pointer's track */
-                               if ((atv2->order - pointer_y_span) > visible_y_high) { // we will overflow 
+                               if ((rtv2->order - pointer_y_span) > visible_y_high) { // we will overflow 
                                        clamp_y_axis = true;
-                               } else if ((atv2->order - pointer_y_span) < visible_y_low) { // we will underflow
+                               } else if ((rtv2->order - pointer_y_span) < visible_y_low) { // we will underflow
                                        clamp_y_axis = true;
                                }
                        }             
@@ -3111,14 +3074,14 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
                        rv->get_canvas_frame()->get_bounds (ix1, iy1, ix2, iy2);
                        rv->get_canvas_group()->i2w (ix1, iy1);
                        TimeAxisView* tvp2 = trackview_by_y_position (iy1);
-                       AudioTimeAxisView* canvas_atv = dynamic_cast<AudioTimeAxisView*>(tvp2);
-                       AudioTimeAxisView* temp_atv;
+                       RouteTimeAxisView* canvas_rtv = dynamic_cast<RouteTimeAxisView*>(tvp2);
+                       RouteTimeAxisView* temp_rtv;
 
                        if ((pointer_y_span != 0) && !clamp_y_axis) {
                                y_delta = 0;
                                int32_t x = 0;
                                for (j = height_list.begin(); j!= height_list.end(); j++) {     
-                                       if (x == canvas_atv->order) {
+                                       if (x == canvas_rtv->order) {
                                                /* we found the track the region is on */
                                                if (x != original_pointer_order) {
                                                        /*this isn't from the same track we're dragging from */
@@ -3156,14 +3119,14 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
                                                /* find out where we'll be when we move and set height accordingly */
                  
                                                tvp2 = trackview_by_y_position (iy1 + y_delta);
-                                               temp_atv = dynamic_cast<AudioTimeAxisView*>(tvp2);
-                                               rv->set_height (temp_atv->height);
+                                               temp_rtv = dynamic_cast<RouteTimeAxisView*>(tvp2);
+                                               rv->set_y_position_and_height (0, temp_rtv->height);
        
                                                /*   if you un-comment the following, the region colours will follow the track colours whilst dragging,
                                                     personally, i think this can confuse things, but never mind.
                                                */
                                  
-                                               //const GdkColor& col (temp_atv->view->get_region_color());
+                                               //const GdkColor& col (temp_rtv->view->get_region_color());
                                                //rv->set_color (const_cast<GdkColor&>(col));
                                                break;          
                                        }
@@ -3231,15 +3194,16 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
        pair<set<boost::shared_ptr<Playlist> >::iterator,bool> insert_result;
        bool nocommit = true;
        double speed;
-       RouteTimeAxisView* atv;
+       RouteTimeAxisView* rtv;
        bool regionview_y_movement;
        bool regionview_x_movement;
+       vector<RegionView*> copies;
 
        /* first_move is set to false if the regionview has been moved in the 
           motion handler. 
        */
 
-       if (drag_info.first_move) {
+       if (drag_info.first_move && !(drag_info.copy && drag_info.x_constrained)) {
                /* just a click */
                goto out;
        }
@@ -3254,15 +3218,22 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
 
        if (drag_info.brushing) {
                /* all changes were made during motion event handlers */
+               
+               if (drag_info.copy) {
+                       for (list<RegionView*>::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
+                               copies.push_back (*i);
+                       }
+               }
+
                goto out;
        }
 
        /* adjust for track speed */
        speed = 1.0;
 
-       atv = dynamic_cast<AudioTimeAxisView*> (drag_info.last_trackview);
-       if (atv && atv->get_diskstream()) {
-               speed = atv->get_diskstream()->speed();
+       rtv = dynamic_cast<RouteTimeAxisView*> (drag_info.last_trackview);
+       if (rtv && rtv->get_diskstream()) {
+               speed = rtv->get_diskstream()->speed();
        }
        
        regionview_x_movement = (drag_info.last_frame_position != (nframes_t) (rv->region()->position()/speed));
@@ -3296,7 +3267,7 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
                vector<RegionView*> new_selection;
 
                for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ) {
-           
+                       
                        RegionView* rv = (*i);              
 
                        double ix1, ix2, iy1, iy2;
@@ -3304,11 +3275,11 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
                        rv->get_canvas_frame()->get_bounds (ix1, iy1, ix2, iy2);
                        rv->get_canvas_group()->i2w (ix1, iy1);
                        TimeAxisView* tvp2 = trackview_by_y_position (iy1);
-                       AudioTimeAxisView* atv2 = dynamic_cast<AudioTimeAxisView*>(tvp2);
+                       RouteTimeAxisView* rtv2 = dynamic_cast<RouteTimeAxisView*>(tvp2);
 
                        boost::shared_ptr<Playlist> from_playlist = rv->region()->playlist();
-                       boost::shared_ptr<Playlist> to_playlist = atv2->playlist();
-           
+                       boost::shared_ptr<Playlist> to_playlist = rtv2->playlist();
+
                        where = (nframes_t) (unit_to_frame (ix1) * speed);
                        boost::shared_ptr<Region> new_region (RegionFactory::create (rv->region()));
 
@@ -3332,11 +3303,17 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
                                session->add_command (new MementoCommand<Playlist>(*from_playlist, &from_playlist->get_state(), 0));    
                                from_playlist->remove_region ((rv->region()));
                                session->add_command (new MementoCommand<Playlist>(*from_playlist, 0, &from_playlist->get_state()));    
+
+                       } else {
+
+                               /* the regionview we dragged around is a temporary copy, queue it for deletion */
+                               
+                               copies.push_back (rv);
                        }
 
                        latest_regionview = 0;
                        
-                       sigc::connection c = atv2->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
+                       sigc::connection c = rtv2->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
                        session->add_command (new MementoCommand<Playlist>(*to_playlist, &to_playlist->get_state(), 0));        
                        to_playlist->add_region (new_region, where);
                        session->add_command (new MementoCommand<Playlist>(*to_playlist, 0, &to_playlist->get_state()));        
@@ -3346,11 +3323,6 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
                                new_selection.push_back (latest_regionview);
                        }
 
-                       if (drag_info.copy) {
-                               // get rid of the copy
-                               delete rv;
-                       } 
-
                        /* OK, this is where it gets tricky. If the playlist was being used by >1 tracks, and the region
                           was selected in all of them, then removing it from the playlist will have removed all
                           trace of it from the selection (i.e. there were N regions selected, we removed 1,
@@ -3363,12 +3335,19 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
                           here. if the region selection is not empty, then restart the loop because we know that
                           we must have removed at least the region(view) we've just been working on as well as any
                           that we processed on previous iterations.
+
+                          EXCEPT .... if we are doing a copy drag, then the selection hasn't been modified and
+                          we can just iterate.
                        */
 
-                       if (selection->regions.empty()) {
-                               break;
-                       } else { 
-                               i = selection->regions.by_layer().begin();
+                       if (drag_info.copy) {
+                               ++i;
+                       } else {
+                               if (selection->regions.empty()) {
+                                       break;
+                               } else { 
+                                       i = selection->regions.by_layer().begin();
+                               }
                        }
                } 
 
@@ -3388,17 +3367,16 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
 
                        rv = (*i);
 
-                       if (rv->region()->locked()) {
+                       if (!rv->region()->can_move()) {
                                continue;
                        }
-                       
 
                        if (regionview_x_movement) {
                                double ownspeed = 1.0;
-                               atv = dynamic_cast<AudioTimeAxisView*> (&(rv->get_time_axis_view()));
+                               rtv = dynamic_cast<RouteTimeAxisView*> (&(rv->get_time_axis_view()));
 
-                               if (atv && atv->get_diskstream()) {
-                                       ownspeed = atv->get_diskstream()->speed();
+                               if (rtv && rtv->get_diskstream()) {
+                                       ownspeed = rtv->get_diskstream()->speed();
                                }
                                
                                /* base the new region position on the current position of the regionview.*/
@@ -3435,21 +3413,17 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
                                }
 
                                /* add it */
-                               
+
                                latest_regionview = 0;
-                               sigc::connection c = atv->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
-                               to_playlist->add_region (newregion, (nframes_t) (where * atv->get_diskstream()->speed()));
+                               sigc::connection c = rtv->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
+                               to_playlist->add_region (newregion, (nframes_t) (where * rtv->get_diskstream()->speed()));
                                c.disconnect ();
                                
                                if (latest_regionview) {
-                                       atv->reveal_dependent_views (*latest_regionview);
+                                       rtv->reveal_dependent_views (*latest_regionview);
                                        selection->add (latest_regionview);
                                }
                                
-                               /* if the original region was locked, we don't care for the new one */
-                               
-                               newregion->set_locked (false);                  
-
                        } else {
 
                                /* just change the model */
@@ -3462,10 +3436,8 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
 
                        session->add_command (new MementoCommand<Playlist>(*to_playlist, 0, &to_playlist->get_state()));
 
-                       /* get rid of the copy */
-
                        if (drag_info.copy) {
-                               delete rv;
+                               copies.push_back (rv);
                        }
                }
        }
@@ -3475,6 +3447,10 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
        if (!nocommit) {
                commit_reversible_command ();
        }
+
+       for (vector<RegionView*>::iterator x = copies.begin(); x != copies.end(); ++x) {
+               delete *x;
+       }
 }
 
 void
@@ -3486,10 +3462,10 @@ Editor::region_view_item_click (AudioRegionView& rv, GdkEventButton* event)
        
        if (Keyboard::modifier_state_contains (event->state, Keyboard::Control)) {
                TimeAxisView* tv = &rv.get_time_axis_view();
-               AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(tv);
+               RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(tv);
                double speed = 1.0;
-               if (atv && atv->is_audio_track()) {
-                       speed = atv->get_diskstream()->speed();
+               if (rtv && rtv->is_track()) {
+                       speed = rtv->get_diskstream()->speed();
                }
 
                if (Keyboard::modifier_state_equals (event->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Alt))) {
@@ -3665,7 +3641,7 @@ Editor::start_selection_grab (ArdourCanvas::Item* item, GdkEvent* event)
        */
        
        latest_regionview = 0;
-       sigc::connection c = clicked_audio_trackview->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
+       sigc::connection c = clicked_routeview->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
        
        /* A selection grab currently creates two undo/redo operations, one for 
           creating the new region and another for moving it.
@@ -3673,11 +3649,11 @@ Editor::start_selection_grab (ArdourCanvas::Item* item, GdkEvent* event)
 
        begin_reversible_command (_("selection grab"));
 
-       boost::shared_ptr<Playlist> playlist = clicked_trackview->playlist();
+       boost::shared_ptr<Playlist> playlist = clicked_axisview->playlist();
 
-        XMLNode *before = &(playlist->get_state());
-       clicked_trackview->playlist()->add_region (region, selection->time[clicked_selection].start);
-        XMLNode *after = &(playlist->get_state());
+       XMLNode *before = &(playlist->get_state());
+       clicked_routeview->playlist()->add_region (region, selection->time[clicked_selection].start);
+       XMLNode *after = &(playlist->get_state());
        session->add_command(new MementoCommand<Playlist>(*playlist, before, after));
 
        commit_reversible_command ();
@@ -3700,7 +3676,7 @@ Editor::start_selection_grab (ArdourCanvas::Item* item, GdkEvent* event)
 
        start_grab (event);
        
-       drag_info.last_trackview = clicked_trackview;
+       drag_info.last_trackview = clicked_axisview;
        drag_info.last_frame_position = latest_regionview->region()->position();
        drag_info.pointer_frame_offset = drag_info.grab_frame - drag_info.last_frame_position;
        
@@ -3746,8 +3722,8 @@ Editor::start_selection_op (ArdourCanvas::Item* item, GdkEvent* event, Selection
                break;
 
        case SelectionStartTrim:
-               if (clicked_trackview) {
-                       clicked_trackview->order_selection_trims (item, true);
+               if (clicked_axisview) {
+                       clicked_axisview->order_selection_trims (item, true);
                } 
                start_grab (event, trimmer_cursor);
                start = selection->time[clicked_selection].start;
@@ -3755,8 +3731,8 @@ Editor::start_selection_op (ArdourCanvas::Item* item, GdkEvent* event, Selection
                break;
                
        case SelectionEndTrim:
-               if (clicked_trackview) {
-                       clicked_trackview->order_selection_trims (item, false);
+               if (clicked_axisview) {
+                       clicked_axisview->order_selection_trims (item, false);
                }
                start_grab (event, trimmer_cursor);
                end = selection->time[clicked_selection].end;
@@ -3831,7 +3807,7 @@ Editor::drag_selection (ArdourCanvas::Item* item, GdkEvent* event)
                                drag_info.copy = false;
                        } else {
                                /* new selection-> */
-                               clicked_selection = selection->set (clicked_trackview, start, end);
+                               clicked_selection = selection->set (clicked_axisview, start, end);
                        }
                } 
                break;
@@ -3935,10 +3911,10 @@ void
 Editor::start_trim (ArdourCanvas::Item* item, GdkEvent* event)
 {
        double speed = 1.0;
-       TimeAxisView* tvp = clicked_trackview;
-       AudioTimeAxisView* tv = dynamic_cast<AudioTimeAxisView*>(tvp);
+       TimeAxisView* tvp = clicked_axisview;
+       RouteTimeAxisView* tv = dynamic_cast<RouteTimeAxisView*>(tvp);
 
-       if (tv && tv->is_audio_track()) {
+       if (tv && tv->is_track()) {
                speed = tv->get_diskstream()->speed();
        }
        
@@ -3993,11 +3969,11 @@ Editor::trim_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
        */ 
 
        double speed = 1.0;
-       TimeAxisView* tvp = clicked_trackview;
+       TimeAxisView* tvp = clicked_axisview;
        RouteTimeAxisView* tv = dynamic_cast<RouteTimeAxisView*>(tvp);
        pair<set<boost::shared_ptr<Playlist> >::iterator,bool> insert_result;
 
-       if (tv && tv->is_audio_track()) {
+       if (tv && tv->is_track()) {
                speed = tv->get_diskstream()->speed();
        }
        
@@ -4121,10 +4097,10 @@ Editor::single_contents_trim (RegionView& rv, nframes_t frame_delta, bool left_d
        nframes_t new_bound;
 
        double speed = 1.0;
-       TimeAxisView* tvp = clicked_trackview;
+       TimeAxisView* tvp = clicked_axisview;
        RouteTimeAxisView* tv = dynamic_cast<RouteTimeAxisView*>(tvp);
 
-       if (tv && tv->is_audio_track()) {
+       if (tv && tv->is_track()) {
                speed = tv->get_diskstream()->speed();
        }
        
@@ -4161,10 +4137,10 @@ Editor::single_start_trim (RegionView& rv, nframes_t frame_delta, bool left_dire
        nframes_t new_bound;
 
        double speed = 1.0;
-       TimeAxisView* tvp = clicked_trackview;
-       AudioTimeAxisView* tv = dynamic_cast<AudioTimeAxisView*>(tvp);
+       TimeAxisView* tvp = clicked_axisview;
+       RouteTimeAxisView* tv = dynamic_cast<RouteTimeAxisView*>(tvp);
 
-       if (tv && tv->is_audio_track()) {
+       if (tv && tv->is_track()) {
                speed = tv->get_diskstream()->speed();
        }
        
@@ -4195,10 +4171,10 @@ Editor::single_end_trim (RegionView& rv, nframes_t frame_delta, bool left_direct
        nframes_t new_bound;
 
        double speed = 1.0;
-       TimeAxisView* tvp = clicked_trackview;
-       AudioTimeAxisView* tv = dynamic_cast<AudioTimeAxisView*>(tvp);
+       TimeAxisView* tvp = clicked_axisview;
+       RouteTimeAxisView* tv = dynamic_cast<RouteTimeAxisView*>(tvp);
 
-       if (tv && tv->is_audio_track()) {
+       if (tv && tv->is_track()) {
                speed = tv->get_diskstream()->speed();
        }
        
@@ -4521,7 +4497,7 @@ Editor::end_range_markerbar_op (ArdourCanvas::Item* item, GdkEvent* event)
                        switch (mouse_mode) {
                        case MouseObject:
                                /* find the two markers on either side and then make the selection from it */
-                               select_all_within (start, end, 0.0f, FLT_MAX, Selection::Set);
+                               select_all_within (start, end, 0.0f, FLT_MAX, track_views, Selection::Set);
                                break;
 
                        case MouseRange:
@@ -4724,9 +4700,9 @@ Editor::end_rubberband_select (ArdourCanvas::Item* item, GdkEvent* event)
                begin_reversible_command (_("rubberband selection"));
 
                if (drag_info.grab_frame < drag_info.last_pointer_frame) {
-                       commit = select_all_within (drag_info.grab_frame, drag_info.last_pointer_frame, y1, y2, op);
+                       commit = select_all_within (drag_info.grab_frame, drag_info.last_pointer_frame, y1, y2, track_views, op);
                } else {
-                       commit = select_all_within (drag_info.last_pointer_frame, drag_info.grab_frame, y1, y2, op);
+                       commit = select_all_within (drag_info.last_pointer_frame, drag_info.grab_frame, y1, y2, track_views, op);
                }               
 
                if (commit) {
@@ -4761,7 +4737,7 @@ Editor::mouse_rename_region (ArdourCanvas::Item* item, GdkEvent* event)
         string str;
                prompter.get_result(str);
                if (str.length()) {
-               clicked_regionview->region()->set_name (str);
+                       clicked_regionview->region()->set_name (str);
                }
                break;
        }
@@ -4854,14 +4830,14 @@ Editor::mouse_brush_insert_region (RegionView* rv, nframes_t pos)
                return;
        }
 
-       RouteTimeAxisView* atv = dynamic_cast<RouteTimeAxisView*>(&arv->get_time_axis_view());
+       RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(&arv->get_time_axis_view());
 
-       if (atv == 0 || !atv->is_audio_track()) {
+       if (rtv == 0 || !rtv->is_track()) {
                return;
        }
 
-       boost::shared_ptr<Playlist> playlist = atv->playlist();
-       double speed = atv->get_diskstream()->speed();
+       boost::shared_ptr<Playlist> playlist = rtv->playlist();
+       double speed = rtv->get_diskstream()->speed();
        
         XMLNode &before = playlist->get_state();
        playlist->add_region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (arv->audio_region())), (nframes_t) (pos * speed));