first pass on track mode switch; fixes to dangling region refs after capture; destroy...
[ardour.git] / gtk2_ardour / region_selection.cc
1 /*
2     Copyright (C) 2006 Paul Davis 
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 */
18
19 #include <algorithm>
20
21 #include <ardour/region.h>
22
23 #include "region_view.h"
24 #include "region_selection.h"
25
26 using namespace ARDOUR;
27 using namespace PBD;
28 using namespace sigc;
29
30
31 bool 
32 RegionComparator::operator() (const RegionView* a, const RegionView* b) const
33 {
34         if (a == b) {
35                 return false;
36         } else {
37                 return a < b;
38         }
39 }
40
41 RegionSelection::RegionSelection ()
42 {
43         _current_start = 0;
44         _current_end = 0;
45 }
46
47 RegionSelection::RegionSelection (const RegionSelection& other)
48 {
49
50         for (RegionSelection::const_iterator i = other.begin(); i != other.end(); ++i) {
51                 add (*i, false);
52         }
53         _current_start = other._current_start;
54         _current_end = other._current_end;
55 }
56
57
58
59 RegionSelection&
60 RegionSelection::operator= (const RegionSelection& other)
61 {
62         if (this != &other) {
63
64                 clear_all();
65                 
66                 for (RegionSelection::const_iterator i = other.begin(); i != other.end(); ++i) {
67                         add (*i, false);
68                 }
69
70                 _current_start = other._current_start;
71                 _current_end = other._current_end;
72         }
73
74         return *this;
75 }
76
77 void
78 RegionSelection::clear_all()
79 {
80         clear();
81         _bylayer.clear();
82         _current_start = 0;
83         _current_end = 0;
84 }
85
86 bool RegionSelection::contains (RegionView* rv)
87 {
88         return this->find (rv) != end();
89 }
90
91 void
92 RegionSelection::add (RegionView* rv, bool dosort)
93 {
94         if (contains (rv)) {
95                 /* we already have it */
96                 return;
97         }
98
99         rv->RegionViewGoingAway.connect (mem_fun(*this, &RegionSelection::remove_it));
100
101         if (rv->region()->first_frame() < _current_start || empty()) {
102                 _current_start = rv->region()->first_frame();
103         }
104         
105         if (rv->region()->last_frame() > _current_end || empty()) {
106                 _current_end = rv->region()->last_frame();
107         }
108         
109         insert (rv);
110
111         // add to layer sorted list
112         add_to_layer (rv);
113         
114 }
115
116 void
117 RegionSelection::remove_it (RegionView *rv)
118 {
119         remove (rv);
120 }
121
122 bool
123 RegionSelection::remove (RegionView* rv)
124 {
125         RegionSelection::iterator i;
126
127         if ((i = this->find (rv)) != end()) {
128
129                 erase (i);
130
131                 // remove from layer sorted list
132                 _bylayer.remove (rv);
133                 
134                 if (empty()) {
135
136                         _current_start = 0;
137                         _current_end = 0;
138
139                 } else {
140                         
141                         boost::shared_ptr<Region> region ((*i)->region());
142
143                         if (region->first_frame() == _current_start) {
144                                 
145                                 /* reset current start */
146                                 
147                                 nframes_t ref = max_frames;
148                                 
149                                 for (i = begin (); i != end(); ++i) {
150                                         if (region->first_frame() < ref) {
151                                                 ref = region->first_frame();
152                                         }
153                                 }
154                                 
155                                 _current_start = ref;
156                                 
157                         }
158                         
159                         if (region->last_frame() == _current_end) {
160
161                                 /* reset current end */
162                                 
163                                 nframes_t ref = 0;
164                                 
165                                 for (i = begin (); i != end(); ++i) {
166                                         if (region->first_frame() > ref) {
167                                                 ref = region->first_frame();
168                                         }
169                                 }
170                                 
171                                 _current_end = ref;
172                         }
173                 }
174
175                 return true;
176         }
177
178         return false;
179 }
180
181 void
182 RegionSelection::add_to_layer (RegionView * rv)
183 {
184         // insert it into layer sorted position
185
186         list<RegionView*>::iterator i;
187
188         for (i = _bylayer.begin(); i != _bylayer.end(); ++i)
189         {
190                 if (rv->region()->layer() < (*i)->region()->layer()) {
191                         _bylayer.insert(i, rv);
192                         return;
193                 }
194         }
195
196         // insert at end if we get here
197         _bylayer.insert(i, rv);
198 }
199
200 struct RegionSortByTime {
201     bool operator() (const RegionView* a, const RegionView* b) {
202             return a->region()->position() < b->region()->position();
203     }
204 };
205
206
207 void
208 RegionSelection::by_position (list<RegionView*>& foo) const
209 {
210         list<RegionView*>::const_iterator i;
211         RegionSortByTime sorter;
212
213         for (i = _bylayer.begin(); i != _bylayer.end(); ++i) {
214                 foo.push_back (*i);
215         }
216
217         foo.sort (sorter);
218         return;
219 }