X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Fregion_selection.cc;h=e5cc93a0b1f50c8b32e05d5a48c0198978da612f;hb=a79fe239355b8c6f4e86da2eb1eec43c6c4dd052;hp=f8c9f384a9b13ce5069dc233b9cb756029016c2c;hpb=6f4a92f740b2fd75794489ce58f9348f8adf6bf4;p=ardour.git diff --git a/gtk2_ardour/region_selection.cc b/gtk2_ardour/region_selection.cc index f8c9f384a9..e5cc93a0b1 100644 --- a/gtk2_ardour/region_selection.cc +++ b/gtk2_ardour/region_selection.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2006 Paul Davis + Copyright (C) 2006 Paul Davis This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,170 +18,148 @@ #include -#include +#include "ardour/region.h" +#include "gui_thread.h" +#include "midi_region_view.h" #include "region_view.h" #include "region_selection.h" +#include "time_axis_view.h" +using namespace std; 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; - } -} +/** Construct an empty RegionSelection. + */ RegionSelection::RegionSelection () { - _current_start = 0; - _current_end = 0; + RegionView::RegionViewGoingAway.connect (death_connection, MISSING_INVALIDATOR, boost::bind (&RegionSelection::remove_it, this, _1), gui_context()); } +/** Copy constructor. + * @param other RegionSelection to copy. + */ RegionSelection::RegionSelection (const RegionSelection& other) + : std::list() { + RegionView::RegionViewGoingAway.connect (death_connection, MISSING_INVALIDATOR, boost::bind (&RegionSelection::remove_it, this, _1), gui_context()); 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; } - - +/** operator= to set a RegionSelection to be the same as another. + * @param other Other RegionSelection. + */ RegionSelection& RegionSelection::operator= (const RegionSelection& other) { if (this != &other) { clear_all(); - + 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; } return *this; } +/** Empty this RegionSelection. + */ void RegionSelection::clear_all() { clear(); + pending.clear (); _bylayer.clear(); } -bool RegionSelection::contains (RegionView* rv) +/** + * @param rv RegionView. + * @return true if this selection contains rv. + */ +bool RegionSelection::contains (RegionView* rv) const { - if (this->find (rv) != end()) { - return true; - } - else { - return false; + return find (begin(), end(), rv) != end(); +} + +bool RegionSelection::contains (boost::shared_ptr region) const +{ + for (const_iterator r = begin (); r != end (); ++r) { + if ((*r)->region () == region) { + return true; + } } - + return false; } -void -RegionSelection::add (RegionView* rv, bool dosort) +/** Add a region to the selection. + * @param rv Region to add. + * @return false if we already had the region or if it cannot be added, + * otherwise true. + */ +bool +RegionSelection::add (RegionView* rv) { - if (this->find (rv) != end()) { + if (!rv->region()->playlist()) { + /* not attached to a playlist - selection not allowed. + This happens if the user tries to select a region + during a capture pass. + */ + return false; + } + + if (contains (rv)) { /* we already have it */ - return; + return false; } - rv->RegionViewGoingAway.connect (mem_fun(*this, &RegionSelection::remove_it)); + push_back (rv); - if (rv->region().first_frame() < _current_start || empty()) { - _current_start = rv->region().first_frame(); - } - - if (rv->region().last_frame() > _current_end || empty()) { - _current_end = rv->region().last_frame(); - } - - insert (rv); + /* add to layer sorted list */ - // add to layer sorted list add_to_layer (rv); - + + return true; } +/** Remove a region from the selection. + * @param rv Region to remove. + */ void RegionSelection::remove_it (RegionView *rv) { remove (rv); } +/** Remove a region from the selection. + * @param rv Region to remove. + * @return true if the region was in the selection, false if not. + */ bool RegionSelection::remove (RegionView* rv) { - RegionSelection::iterator i; - - if ((i = this->find (rv)) != end()) { + RegionSelection::iterator r; - erase (i); + if ((r = find (begin(), end(), rv)) != end()) { // remove from layer sorted list _bylayer.remove (rv); - - if (empty()) { - - _current_start = 0; - _current_end = 0; - - } else { - - Region& region ((*i)->region()); - - if (region.first_frame() == _current_start) { - - /* reset current start */ - - jack_nframes_t ref = max_frames; - - for (i = begin (); i != end(); ++i) { - if (region.first_frame() < ref) { - ref = region.first_frame(); - } - } - - _current_start = ref; - - } - - if (region.last_frame() == _current_end) { - - /* reset current end */ - - jack_nframes_t ref = 0; - - for (i = begin (); i != end(); ++i) { - if (region.first_frame() > ref) { - ref = region.first_frame(); - } - } - - _current_end = ref; - } - } - + pending.remove (rv->region()->id()); + erase (r); return true; } return false; } +/** Add a region to the list sorted by layer. + * @param rv Region to add. + */ void RegionSelection::add_to_layer (RegionView * rv) { @@ -191,7 +169,7 @@ RegionSelection::add_to_layer (RegionView * rv) for (i = _bylayer.begin(); i != _bylayer.end(); ++i) { - if (rv->region().layer() < (*i)->region().layer()) { + if (rv->region()->layer() < (*i)->region()->layer()) { _bylayer.insert(i, rv); return; } @@ -202,12 +180,16 @@ RegionSelection::add_to_layer (RegionView * rv) } struct RegionSortByTime { - bool operator() (const RegionView* a, const RegionView* b) { - return a->region().position() < b->region().position(); - } + bool operator() (const RegionView* a, const RegionView* b) const { + return a->region()->position() < b->region()->position(); + } }; +/** + * @param foo List which will be filled with the selection's regions + * sorted by position. + */ void RegionSelection::by_position (list& foo) const { @@ -221,3 +203,123 @@ 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_time_axis_view().order() == b->get_time_axis_view().order()) { + return a->region()->position() < b->region()->position(); + } else { + return a->get_time_axis_view().order() < b->get_time_axis_view().order(); + } + } +}; + + +/** + * @param List which will be filled with the selection's regions + * sorted by track and position. + */ +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; +} + +/** + * @param Sort the selection by position and track. + */ +void +RegionSelection::sort_by_position_and_track () +{ + RegionSortByTrack sorter; + sort (sorter); +} + +/** + * @param tv Track. + * @return true if any of the selection's regions are on tv. + */ +bool +RegionSelection::involves (const TimeAxisView& tv) const +{ + for (RegionSelection::const_iterator i = begin(); i != end(); ++i) { + if (&(*i)->get_time_axis_view() == &tv) { + return true; + } + } + return false; +} + +samplepos_t +RegionSelection::start () const +{ + samplepos_t s = max_samplepos; + for (RegionSelection::const_iterator i = begin(); i != end(); ++i) { + s = min (s, (*i)->region()->position ()); + } + + if (s == max_samplepos) { + return 0; + } + + return s; +} + +samplepos_t +RegionSelection::end_sample () const +{ + samplepos_t e = 0; + for (RegionSelection::const_iterator i = begin(); i != end(); ++i) { + e = max (e, (*i)->region()->last_sample ()); + } + + return e; +} + +/** @return the playlists that the regions in the selection are on */ +set > +RegionSelection::playlists () const +{ + set > pl; + for (RegionSelection::const_iterator i = begin(); i != end(); ++i) { + pl.insert ((*i)->region()->playlist ()); + } + + return pl; +} + +size_t +RegionSelection::n_midi_regions () const +{ + size_t count = 0; + + for (const_iterator r = begin(); r != end(); ++r) { + MidiRegionView* const mrv = dynamic_cast (*r); + if (mrv) { + ++count; + } + } + + return count; +} + +ARDOUR::RegionList +RegionSelection::regionlist () const +{ + ARDOUR::RegionList rl; + for (const_iterator r = begin (); r != end (); ++r) { + rl.push_back ((*r)->region ()); + } + return rl; +}