major chunk of the region layering editor from 2.X, fwd-ported to 3.0
authorPaul Davis <paul@linuxaudiosystems.com>
Wed, 25 Aug 2010 19:28:33 +0000 (19:28 +0000)
committerPaul Davis <paul@linuxaudiosystems.com>
Wed, 25 Aug 2010 19:28:33 +0000 (19:28 +0000)
git-svn-id: svn://localhost/ardour2/branches/3.0@7689 d708f5d6-7413-0410-9779-e7cbd77b26cf

gtk2_ardour/editor.cc
gtk2_ardour/editor.h
gtk2_ardour/editor_mouse.cc
gtk2_ardour/wscript
libs/ardour/ardour/playlist.h
libs/ardour/playlist.cc

index e1e4714eb38f5fb82dc0452573d006dfe05823e1..aa0a76edcda0759ad9fb2586bf9e2ddfc7cf8c28 100644 (file)
 #include "editor_locations.h"
 #include "editor_snapshots.h"
 #include "editor_summary.h"
+#include "region_layering_order_editor.h"
 
 #include "i18n.h"
 
@@ -384,6 +385,7 @@ Editor::Editor ()
        _dragging_edit_point = false;
        select_new_marker = false;
        rhythm_ferret = 0;
+        layering_order_editor = 0;
        _bundle_manager = 0;
        no_save_visual = false;
        resize_idle_id = -1;
@@ -748,7 +750,7 @@ Editor::~Editor()
                image_socket_listener = 0 ;
        }
 #endif
-
+        
        delete _routes;
        delete _route_groups;
        delete track_canvas;
@@ -1522,28 +1524,26 @@ Editor::build_track_region_context_menu (nframes64_t frame)
                   mode and so offering region context is somewhat confusing.
                */
                if ((tr = rtv->track()) && ((pl = tr->playlist())) && !internal_editing()) {
-                       Playlist::RegionList* regions = pl->regions_at ((nframes64_t) floor ( (double)frame * tr->speed()));
+                        framepos_t framepos = (framepos_t) floor ((double)frame * tr->speed());
+                        uint32_t regions_at = pl->count_regions_at (framepos);
+                        list<boost::shared_ptr<Region> > regions_for_menu;
 
                        if (selection->regions.size() > 1) {
                                // there's already a multiple selection: just add a
                                // single region context menu that will act on all
                                // selected regions
 
-                               list<boost::shared_ptr<Region> > regions;
                                for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
-                                       regions.push_back ((*i)->region ());
+                                       regions_for_menu.push_back ((*i)->region ());
                                }
-                               
-                               add_region_context_items (rtv->view(), regions, edit_items);
-                       } else {
-                               for (Playlist::RegionList::reverse_iterator i = regions->rbegin(); i != regions->rend(); ++i) {
-                                       list<boost::shared_ptr<Region> > regions;
-                                       regions.push_back (*i);
-                                       add_region_context_items (rtv->view(), regions, edit_items);
-                               }
-                       }
+                        } else {
+                                boost::shared_ptr<Region> top_region = pl->top_region_at (framepos);
+                                if (top_region) {
+                                        regions_for_menu.push_back (top_region);
+                                }
+                        }
 
-                       delete regions;
+                        add_region_context_items (rtv->view(), regions_for_menu, edit_items, framepos, regions_at > 1);
                }
        }
 
@@ -1568,7 +1568,6 @@ Editor::build_track_crossfade_context_menu (nframes64_t frame)
 
                if ((tr = atv->track()) && ((pl = tr->playlist()) != 0) && ((apl = boost::dynamic_pointer_cast<AudioPlaylist> (pl)) != 0)) {
 
-                       Playlist::RegionList* regions = pl->regions_at (frame);
                        AudioPlaylist::Crossfades xfades;
 
                        apl->crossfades_at (frame, xfades);
@@ -1579,25 +1578,26 @@ Editor::build_track_crossfade_context_menu (nframes64_t frame)
                                add_crossfade_context_items (atv->audio_view(), (*i), edit_items, many);
                        }
 
+                       framepos_t framepos = (framepos_t) floor ((double)frame * tr->speed());
+                       uint32_t regions_at = pl->count_regions_at (framepos);
+                        list<boost::shared_ptr<Region> > regions_for_menu;
+
                        if (selection->regions.size() > 1) {
-                               // there's already a multiple selection: just add a
-                               // single region context menu that will act on all
-                               // selected regions
+                               // there's already a multiple selection: just add a
+                               // single region context menu that will act on all
+                               // selected regions
 
-                               list<boost::shared_ptr<Region> > regions;
                                for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
-                                       regions.push_back ((*i)->region ());
+                                       regions_for_menu.push_back ((*i)->region ());
                                }
-
-                               add_region_context_items (atv->audio_view(), regions, edit_items);
-                       } else {
-                               for (Playlist::RegionList::reverse_iterator i = regions->rbegin(); i != regions->rend(); ++i) {
-                                       list<boost::shared_ptr<Region> > regions;
-                                       regions.push_back (*i);
-                                       add_region_context_items (atv->audio_view(), regions, edit_items);
-                               }
-                       }
-                       delete regions;
+                        } else {
+                                boost::shared_ptr<Region> top_region = pl->top_region_at (framepos);
+                                if (top_region) {
+                                        regions_for_menu.push_back (top_region);
+                                }
+                        }
+                        
+                        add_region_context_items (atv->audio_view(), regions_for_menu, edit_items, framepos, regions_at > 1);
                }
        }
 
@@ -1717,7 +1717,8 @@ Editor::xfade_edit_right_region ()
 }
 
 void
-Editor::add_region_context_items (StreamView* sv, list<boost::shared_ptr<Region> > regions, Menu_Helpers::MenuList& edit_items)
+Editor::add_region_context_items (StreamView* sv, list<boost::shared_ptr<Region> > regions, Menu_Helpers::MenuList& edit_items,
+                                  framepos_t position, bool multiple_regions_at_position)
 {
        using namespace Menu_Helpers;
        Gtk::MenuItem* foo_item;
@@ -2015,6 +2016,9 @@ Editor::add_region_context_items (StreamView* sv, list<boost::shared_ptr<Region>
        }
 
        edit_items.push_back (MenuElem (menu_item_name, *region_menu));
+       if (multiple_regions_at_position && (layering_order_editor == 0 || !layering_order_editor->is_visible ())) {
+               edit_items.push_back (MenuElem (_("Choose top region"), (bind (mem_fun(*this, &Editor::change_region_layering_order), position))));
+       }
        edit_items.push_back (SeparatorElem());
 }
 
@@ -5565,3 +5569,44 @@ Editor::show_editor_list (bool yn)
        }
 }
 
+void
+Editor::change_region_layering_order (framepos_t position)
+{
+       if (!clicked_regionview) {
+                if (layering_order_editor) {
+                        layering_order_editor->hide ();
+                }
+               return;
+       }
+
+        if (!clicked_routeview) {
+               return;
+       }
+
+        boost::shared_ptr<Track> track = boost::dynamic_pointer_cast<Track> (clicked_routeview->route());
+
+        if (!track) {
+                return;
+        }
+
+       boost::shared_ptr<Playlist> pl = track->playlist();
+
+       if (!pl) {
+                return;
+        }
+                
+        if (layering_order_editor == 0) {
+                layering_order_editor = new RegionLayeringOrderEditor(*this);
+        }
+
+        layering_order_editor->set_context (clicked_routeview->name(), _session, pl, position);
+        layering_order_editor->maybe_present ();
+}
+
+void
+Editor::update_region_layering_order_editor (framepos_t frame)
+{
+       if (layering_order_editor && layering_order_editor->is_visible ()) {
+               change_region_layering_order (frame);
+       }
+}
index 2d4a8d453e9757d913583e73565e985e3d476c85..3b306e1594b3c2b89a403b0b61432d7f17db40e6 100644 (file)
@@ -128,6 +128,7 @@ class EditorRegions;
 class EditorLocations;
 class EditorSnapshots;
 class EditorSummary;
+class RegionLayeringOrderEditor;
 
 /* <CMT Additions> */
 class ImageFrameView;
@@ -672,7 +673,8 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
        Gtk::Menu* build_track_selection_context_menu (nframes64_t);
        void add_dstream_context_items (Gtk::Menu_Helpers::MenuList&);
        void add_bus_context_items (Gtk::Menu_Helpers::MenuList&);
-       void add_region_context_items (StreamView*, std::list<boost::shared_ptr<ARDOUR::Region> >, Gtk::Menu_Helpers::MenuList&);
+       void add_region_context_items (StreamView*, std::list<boost::shared_ptr<ARDOUR::Region> >, Gtk::Menu_Helpers::MenuList&,
+                                       ARDOUR::framepos_t, bool);
        void add_crossfade_context_items (AudioStreamView*, boost::shared_ptr<ARDOUR::Crossfade>, Gtk::Menu_Helpers::MenuList&, bool many);
        void add_selection_context_items (Gtk::Menu_Helpers::MenuList&);
 
@@ -1062,6 +1064,7 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
        void toggle_region_lock_style ();
        void raise_region ();
        void raise_region_to_top ();
+        void change_region_layering_order (ARDOUR::framepos_t);
        void lower_region ();
        void lower_region_to_bottom ();
        void split_regions_at (nframes64_t, RegionSelection&);
@@ -2044,6 +2047,9 @@ public:
 
        double _last_motion_y;
 
+        RegionLayeringOrderEditor* layering_order_editor;
+        void update_region_layering_order_editor (ARDOUR::framepos_t);
+
        friend class Drag;
        friend class RegionDrag;
        friend class RegionMoveDrag;
index 296a6ee3285534d46461d14bf6f2129cfc23c41f..a7b370a04b91979de38d8df9ad9c14e65acec1f0 100644 (file)
@@ -1117,7 +1117,7 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp
 bool
 Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type)
 {
-       nframes64_t where = event_frame (event, 0, 0);
+       framepos_t where = event_frame (event, 0, 0);
        AutomationTimeAxisView* atv = 0;
 
        /* no action if we're recording */
@@ -1139,6 +1139,8 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
                were_dragging = true;
        }
 
+        update_region_layering_order_editor (where);
+
        /* edit events get handled here */
 
        if (!_drags->active () && Keyboard::is_edit_event (&event->button)) {
index 4b24082d47f8b95050661a516a5356c4513e9710..042fa7cc569eb4a1956606a0ebfee66a3ce44221 100644 (file)
@@ -170,6 +170,7 @@ gtk2_ardour_sources = [
        'rc_option_editor.cc',
        'region_editor.cc',
        'region_gain_line.cc',
+       'region_layering_order_editor.cc',
        'region_selection.cc',
        'region_view.cc',
        'return_ui.cc',
index 624f0a3da15e12fb2f08466b60ac43405469f33c..6473211126480d4cc6b3cded77e4b36e28cbcaf5 100644 (file)
@@ -144,6 +144,7 @@ public:
        const RegionListProperty& region_list () const { return regions; }
 
        RegionList*                regions_at (framepos_t frame);
+        uint32_t                   count_regions_at (framepos_t);
        RegionList*                regions_touched (framepos_t start, framepos_t end);
        RegionList*                regions_to_read (framepos_t start, framepos_t end);
        boost::shared_ptr<Region>  find_region (const PBD::ID&) const;
@@ -326,7 +327,7 @@ public:
        bool add_region_internal (boost::shared_ptr<Region>, framepos_t position);
 
        int remove_region_internal (boost::shared_ptr<Region>);
-       RegionList *find_regions_at (framepos_t frame);
+       RegionList *find_regions_at (framepos_t);
        void copy_regions (RegionList&) const;
        void partition_internal (framepos_t start, framepos_t end, bool cutting, RegionList& thawlist);
 
index 93cfbab1fc687b9f8591e3aec9526a6c524a145c..9c980ff73556fff7694fc2850c0cd0de8ddb0579 100644 (file)
@@ -1665,6 +1665,21 @@ Playlist::regions_at (framepos_t frame)
        return find_regions_at (frame);
 }
 
+uint32_t
+Playlist::count_regions_at (framepos_t frame)
+{
+       RegionLock rlock (this);
+       uint32_t cnt = 0;
+
+       for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
+               if ((*i)->covers (frame)) {
+                       cnt++;
+               }
+       }
+
+       return cnt;
+}
+
 boost::shared_ptr<Region>
 Playlist::top_region_at (framepos_t frame)
 
@@ -2463,10 +2478,10 @@ Playlist::relayer ()
 void
 Playlist::raise_region (boost::shared_ptr<Region> region)
 {
-       uint32_t rsz = regions.size();
+       uint32_t top = regions.size() - 1;
        layer_t target = region->layer() + 1U;
 
-       if (target >= rsz) {
+       if (target >= top) {
                /* its already at the effective top */
                return;
        }