From 762d2ae936bd78053d9f344ce9392b7867304ae2 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Wed, 17 Jan 2007 01:42:44 +0000 Subject: fix ordering of cut/copied regions when pasting; ctrl-click now does the right thing the first time its used on a region; fix missing click and other dubious behaviour in new sessions caused by not connecting to Configuration::ParameterChanged in the new session constructor git-svn-id: svn://localhost/ardour2/trunk@1331 d708f5d6-7413-0410-9779-e7cbd77b26cf --- gtk2_ardour/actions.cc | 2 +- gtk2_ardour/ardour_ui_options.cc | 1 + gtk2_ardour/editor.cc | 20 +++- gtk2_ardour/editor.h | 2 + gtk2_ardour/editor_keyboard.cc | 2 +- gtk2_ardour/editor_mixer.cc | 3 + gtk2_ardour/editor_ops.cc | 147 ++++++++++++++++++---------- gtk2_ardour/region_selection.cc | 62 ++++++++---- gtk2_ardour/region_selection.h | 16 ++- gtk2_ardour/time_axis_view_item.h | 5 + libs/ardour/ardour/configuration_variable.h | 6 ++ libs/ardour/configuration.cc | 13 +++ libs/ardour/session.cc | 3 +- 13 files changed, 200 insertions(+), 82 deletions(-) diff --git a/gtk2_ardour/actions.cc b/gtk2_ardour/actions.cc index 2fe305cf84..d382878582 100644 --- a/gtk2_ardour/actions.cc +++ b/gtk2_ardour/actions.cc @@ -266,7 +266,7 @@ ActionManager::toggle_config_state (const char* group, const char* action, bool if (tact) { bool x = (Config->*get)(); - + if (x != tact->get_active()) { (Config->*set) (!x); } diff --git a/gtk2_ardour/ardour_ui_options.cc b/gtk2_ardour/ardour_ui_options.cc index d0f523481f..7b8557f18b 100644 --- a/gtk2_ardour/ardour_ui_options.cc +++ b/gtk2_ardour/ardour_ui_options.cc @@ -19,6 +19,7 @@ */ #include +#include #include diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc index cd1e9f3f61..e447603100 100644 --- a/gtk2_ardour/editor.cc +++ b/gtk2_ardour/editor.cc @@ -28,6 +28,7 @@ #include #include +#include #include #include @@ -3030,7 +3031,6 @@ Editor::mapped_set_selected_regionview_from_click (RouteTimeAxisView& tv, uint32 return; } - if ((pl = ds->playlist()) != 0) { pl->get_equivalent_regions (basis->region(), results); } @@ -3052,6 +3052,10 @@ Editor::set_selected_regionview_from_click (bool press, Selection::Operation op, return false; } + if (press) { + button_release_can_deselect = false; + } + if (op == Selection::Toggle || op == Selection::Set) { mapover_audio_tracks (bind (mem_fun (*this, &Editor::mapped_set_selected_regionview_from_click), @@ -4292,3 +4296,17 @@ Editor::idle_visual_changer () return 0; } + +struct EditorOrderTimeAxisSorter { + bool operator() (const TimeAxisView* a, const TimeAxisView* b) const { + return a->order < b->order; + } +}; + +void +Editor::sort_track_selection () +{ + EditorOrderTimeAxisSorter cmp; + selection->tracks.sort (cmp); +} + diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index 241ce808ff..b09f76c9d9 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -419,6 +419,8 @@ class Editor : public PublicEditor CrossfadeView* clicked_crossfadeview; ControlPoint* clicked_control_point; + void sort_track_selection (); + void get_relevant_audio_tracks (std::set& relevant_tracks); void mapover_audio_tracks (sigc::slot sl); diff --git a/gtk2_ardour/editor_keyboard.cc b/gtk2_ardour/editor_keyboard.cc index cdea9d2272..bfe61eae5c 100644 --- a/gtk2_ardour/editor_keyboard.cc +++ b/gtk2_ardour/editor_keyboard.cc @@ -82,7 +82,7 @@ Editor::kbd_do_split (GdkEvent* ev) nframes_t where = event_frame (ev); if (entered_regionview) { - if (selection->regions.find (entered_regionview) != selection->regions.end()) { + if (selection->regions.contains (entered_regionview)) { split_regions_at (where, selection->regions); } else { RegionSelection s; diff --git a/gtk2_ardour/editor_mixer.cc b/gtk2_ardour/editor_mixer.cc index 2d8d04e94a..13eafe1602 100644 --- a/gtk2_ardour/editor_mixer.cc +++ b/gtk2_ardour/editor_mixer.cc @@ -77,6 +77,9 @@ Editor::show_editor_mixer (bool yn) } } else { + + sort_track_selection (); + for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) { AudioTimeAxisView* atv; diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc index 2e271d7671..5ab343392a 100644 --- a/gtk2_ardour/editor_ops.cc +++ b/gtk2_ardour/editor_ops.cc @@ -1351,27 +1351,20 @@ Editor::select_all_within (nframes_t start, nframes_t end, double top, double bo (*iter)->get_selectables (start, end, top, bot, touched); } - cerr << "select all within found " << touched.size() << endl; - begin_reversible_command (_("select all within")); switch (op) { case Selection::Add: case Selection::Toggle: - cerr << "toggle\n"; selection->add (touched); break; case Selection::Set: - cerr << "set\n"; selection->set (touched); break; case Selection::Extend: - cerr << "extend\n"; /* not defined yet */ break; } - cerr << "selection now has " << selection->points.size() << endl; - commit_reversible_command (); return !touched.empty(); } @@ -2166,6 +2159,8 @@ Editor::create_region_from_selection (vector >& n nframes_t start = selection->time[clicked_selection].start; nframes_t end = selection->time[clicked_selection].end; + sort_track_selection (); + for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) { boost::shared_ptr current; @@ -2227,6 +2222,8 @@ Editor::separate_region_from_selection () boost::shared_ptr playlist; + sort_track_selection (); + for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) { AudioTimeAxisView* atv; @@ -2333,6 +2330,8 @@ Editor::crop_region_to_selection () } else { + sort_track_selection (); + for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) { AudioTimeAxisView* atv; @@ -2949,17 +2948,33 @@ struct lt_playlist { } }; +struct PlaylistMapping { + TimeAxisView* tv; + boost::shared_ptr pl; + + PlaylistMapping (TimeAxisView* tvp) : tv (tvp) {} +}; + void Editor::cut_copy_regions (CutCopyOp op) { - typedef std::map,boost::shared_ptr > PlaylistMapping; - PlaylistMapping pmap; - nframes_t first_position = max_frames; + /* we can't use a std::map here because the ordering is important, and we can't trivially sort + a map when we want ordered access to both elements. i think. + */ + + vector pmap; + nframes_t first_position = max_frames; + set freezelist; pair::iterator,bool> insert_result; + + /* get ordering correct before we cut/copy */ + + selection->regions.sort_by_position_and_track (); for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) { + first_position = min ((*x)->region()->position(), first_position); if (op == Cut || op == Clear) { @@ -2972,66 +2987,94 @@ Editor::cut_copy_regions (CutCopyOp op) before.before = &pl->get_state(); insert_result = freezelist.insert (before); - + if (insert_result.second) { pl->freeze (); } } } + + TimeAxisView* tv = &(*x)->get_trackview(); + vector::iterator z; + + for (z = pmap.begin(); z != pmap.end(); ++z) { + if ((*z).tv == tv) { + break; + } + } + + if (z == pmap.end()) { + pmap.push_back (PlaylistMapping (tv)); + } } for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ) { boost::shared_ptr pl = boost::dynamic_pointer_cast((*x)->region()->playlist()); + + if (!pl) { + /* impossible, but this handles it for the future */ + continue; + } + + TimeAxisView& tv = (*x)->get_trackview(); boost::shared_ptr npl; RegionSelection::iterator tmp; tmp = x; ++tmp; - if (pl) { - - PlaylistMapping::iterator pi = pmap.find (pl); - - if (pi == pmap.end()) { - npl = boost::dynamic_pointer_cast (PlaylistFactory::create (*session, "cutlist", true)); - npl->freeze(); - pmap[pl] = npl; - } else { - npl = pi->second; - } - - // FIXME - boost::shared_ptr ar = boost::dynamic_pointer_cast((*x)->region()); - switch (op) { - case Cut: - if (!ar) break; - - npl->add_region (RegionFactory::create (ar), (*x)->region()->position() - first_position); - pl->remove_region (((*x)->region())); - break; - - case Copy: - if (!ar) break; - - npl->add_region (RegionFactory::create (ar), (*x)->region()->position() - first_position); - break; - - case Clear: - pl->remove_region (((*x)->region())); + vector::iterator z; + + for (z = pmap.begin(); z != pmap.end(); ++z) { + if ((*z).tv == &tv) { break; } } + + assert (z != pmap.end()); + + if (!(*z).pl) { + npl = boost::dynamic_pointer_cast (PlaylistFactory::create (*session, "cutlist", true)); + npl->freeze(); + (*z).pl = npl; + } else { + npl = (*z).pl; + } + + boost::shared_ptr ar = boost::dynamic_pointer_cast((*x)->region()); + + switch (op) { + case Cut: + if (!ar) break; + + npl->add_region (RegionFactory::create (ar), (*x)->region()->position() - first_position); + pl->remove_region (((*x)->region())); + break; + + case Copy: + if (!ar) break; + + npl->add_region (RegionFactory::create (ar), (*x)->region()->position() - first_position); + break; + + case Clear: + pl->remove_region (((*x)->region())); + break; + } x = tmp; } - + list > foo; - - for (PlaylistMapping::iterator i = pmap.begin(); i != pmap.end(); ++i) { - foo.push_back (i->second); + + /* the pmap is in the same order as the tracks in which selected regions occured */ + + for (vector::iterator i = pmap.begin(); i != pmap.end(); ++i) { + (*i).pl->thaw(); + foo.push_back ((*i).pl); } - + if (!foo.empty()) { cut_buffer->set (foo); } @@ -3095,15 +3138,19 @@ Editor::paste_internal (nframes_t position, float times) TrackSelection::iterator i; size_t nth; + /* get everything in the correct order */ + + sort_track_selection (); + for (nth = 0, i = selection->tracks.begin(); i != selection->tracks.end(); ++i, ++nth) { - + /* undo/redo is handled by individual tracks */ if ((*i)->paste (position, times, *cut_buffer, nth)) { commit = true; } } - + if (commit) { commit_reversible_command (); } @@ -3129,6 +3176,8 @@ Editor::paste_named_selection (float times) chunk = ns->playlists.begin(); begin_reversible_command (_("paste chunk")); + + sort_track_selection (); for (t = selection->tracks.begin(); t != selection->tracks.end(); ++t) { @@ -3241,8 +3290,6 @@ Editor::reset_point_selection () { /* reset all selected points to the relevant default value */ - cerr << "point selection has " << selection->points.size() << " entries\n"; - for (PointSelection::iterator i = selection->points.begin(); i != selection->points.end(); ++i) { AutomationTimeAxisView* atv = dynamic_cast(&(*i).track); diff --git a/gtk2_ardour/region_selection.cc b/gtk2_ardour/region_selection.cc index a418b1de23..430e1d3728 100644 --- a/gtk2_ardour/region_selection.cc +++ b/gtk2_ardour/region_selection.cc @@ -22,22 +22,13 @@ #include "region_view.h" #include "region_selection.h" +#include "time_axis_view.h" using namespace ARDOUR; using namespace PBD; using namespace sigc; -bool -RegionComparator::operator() (const RegionView* a, const RegionView* b) const -{ - if (a == b) { - return false; - } else { - return a < b; - } -} - RegionSelection::RegionSelection () { _current_start = 0; @@ -46,9 +37,8 @@ RegionSelection::RegionSelection () RegionSelection::RegionSelection (const RegionSelection& other) { - for (RegionSelection::const_iterator i = other.begin(); i != other.end(); ++i) { - add (*i, false); + add (*i); } _current_start = other._current_start; _current_end = other._current_end; @@ -64,7 +54,7 @@ RegionSelection::operator= (const RegionSelection& other) clear_all(); for (RegionSelection::const_iterator i = other.begin(); i != other.end(); ++i) { - add (*i, false); + add (*i); } _current_start = other._current_start; @@ -85,11 +75,11 @@ RegionSelection::clear_all() bool RegionSelection::contains (RegionView* rv) { - return this->find (rv) != end(); + return find (begin(), end(), rv) != end(); } void -RegionSelection::add (RegionView* rv, bool dosort) +RegionSelection::add (RegionView* rv) { if (contains (rv)) { /* we already have it */ @@ -106,11 +96,11 @@ RegionSelection::add (RegionView* rv, bool dosort) _current_end = rv->region()->last_frame(); } - insert (rv); + push_back (rv); // add to layer sorted list + add_to_layer (rv); - } void @@ -124,7 +114,7 @@ RegionSelection::remove (RegionView* rv) { RegionSelection::iterator i; - if ((i = this->find (rv)) != end()) { + if ((i = find (begin(), end(), rv)) != end()) { erase (i); @@ -198,7 +188,7 @@ RegionSelection::add_to_layer (RegionView * rv) } struct RegionSortByTime { - bool operator() (const RegionView* a, const RegionView* b) { + bool operator() (const RegionView* a, const RegionView* b) const { return a->region()->position() < b->region()->position(); } }; @@ -217,3 +207,37 @@ RegionSelection::by_position (list& foo) const foo.sort (sorter); return; } + +struct RegionSortByTrack { + bool operator() (const RegionView* a, const RegionView* b) const { + + /* really, track and position */ + + if (a->get_trackview().order == b->get_trackview().order) { + return a->region()->position() < b->region()->position(); + } else { + return a->get_trackview().order < b->get_trackview().order; + } + } +}; + +void +RegionSelection::by_track (list& foo) const +{ + list::const_iterator i; + RegionSortByTrack sorter; + + for (i = _bylayer.begin(); i != _bylayer.end(); ++i) { + foo.push_back (*i); + } + + foo.sort (sorter); + return; +} + +void +RegionSelection::sort_by_position_and_track () +{ + RegionSortByTrack sorter; + sort (sorter); +} diff --git a/gtk2_ardour/region_selection.h b/gtk2_ardour/region_selection.h index 7e1d3b0835..5c05a813f9 100644 --- a/gtk2_ardour/region_selection.h +++ b/gtk2_ardour/region_selection.h @@ -29,11 +29,7 @@ using std::set; class RegionView; -struct RegionComparator { - bool operator() (const RegionView* a, const RegionView* b) const; -}; - -class RegionSelection : public set, public sigc::trackable +class RegionSelection : public std::list, public sigc::trackable { public: RegionSelection(); @@ -41,9 +37,10 @@ class RegionSelection : public set, public sigc:: RegionSelection& operator= (const RegionSelection&); - void add (RegionView*, bool dosort = true); + void add (RegionView*); bool remove (RegionView*); bool contains (RegionView*); + void sort_by_position_and_track (); void clear_all(); @@ -51,14 +48,15 @@ class RegionSelection : public set, public sigc:: return _current_start; } - /* collides with list<>::end */ + /* "end" collides with list<>::end */ nframes_t end_frame () const { return _current_end; } - const list & by_layer() const { return _bylayer; } - void by_position (list&) const; + const std::list& by_layer() const { return _bylayer; } + void by_position (std::list&) const; + void by_track (std::list&) const; private: void remove_it (RegionView*); diff --git a/gtk2_ardour/time_axis_view_item.h b/gtk2_ardour/time_axis_view_item.h index e27b944e2a..80d9177041 100644 --- a/gtk2_ardour/time_axis_view_item.h +++ b/gtk2_ardour/time_axis_view_item.h @@ -232,6 +232,11 @@ class TimeAxisViewItem : public Selectable ArdourCanvas::Text* get_name_text(); + /** + * Returns the time axis that this item is upon + */ + TimeAxisView& get_trackview() const { return trackview; } + /** * Sets the samples per unit of this item. * this item is used to determine the relative visual size and position of this item diff --git a/libs/ardour/ardour/configuration_variable.h b/libs/ardour/ardour/configuration_variable.h index 6f0a8a3571..4327fa69b1 100644 --- a/libs/ardour/ardour/configuration_variable.h +++ b/libs/ardour/ardour/configuration_variable.h @@ -27,9 +27,13 @@ class ConfigVariableBase { virtual void add_to_node (XMLNode& node) = 0; virtual bool set_from_node (const XMLNode& node, Owner owner) = 0; + protected: std::string _name; Owner _owner; + + void notify (); + void miss (); }; template @@ -41,10 +45,12 @@ class ConfigVariable : public ConfigVariableBase virtual bool set (T val, Owner owner) { if (val == value) { + miss (); return false; } value = val; _owner = (ConfigVariableBase::Owner)(_owner |owner); + notify (); return true; } diff --git a/libs/ardour/configuration.cc b/libs/ardour/configuration.cc index eb3d879447..a0f2b5e036 100644 --- a/libs/ardour/configuration.cc +++ b/libs/ardour/configuration.cc @@ -317,3 +317,16 @@ Configuration::map_parameters (sigc::slot theSlot) #undef CONFIG_VARIABLE #undef CONFIG_VARIABLE_SPECIAL } + +void +ConfigVariableBase::notify () +{ + // placeholder for any debugging desired when a config variable is modified +} + +void +ConfigVariableBase::miss () +{ + // placeholder for any debugging desired when a config variable + // is set but to the same value as it already has +} diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index d49fb2c116..eba090665a 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -368,7 +368,6 @@ Session::Session (AudioEngine &eng, if (master_out_channels) { shared_ptr r (new Route (*this, _("master"), -1, master_out_channels, -1, master_out_channels, Route::MasterOut)); r->set_remote_control_id (control_id); - cerr << "master bus has remote control ID " << r->remote_control_id() << endl; rl.push_back (r); } else { @@ -396,6 +395,8 @@ Session::Session (AudioEngine &eng, _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty); + Config->ParameterChanged.connect (mem_fun (*this, &Session::config_changed)); + if (was_dirty) { DirtyChanged (); /* EMIT SIGNAL */ } -- cgit v1.2.3