Merging from trunk
[ardour.git] / gtk2_ardour / region_selection.cc
1 #include <algorithm>
2
3 #include <ardour/audioregion.h>
4
5 #include "regionview.h"
6 #include "region_selection.h"
7
8 using namespace ARDOUR;
9 using namespace PBD;
10 using namespace sigc;
11
12
13 bool 
14 AudioRegionComparator::operator() (const AudioRegionView* a, const AudioRegionView* b) const
15 {
16         if (a == b) {
17                 return false;
18         } else {
19                 return a < b;
20         }
21 }
22
23 AudioRegionSelection::AudioRegionSelection ()
24 {
25         _current_start = 0;
26         _current_end = 0;
27 }
28
29 AudioRegionSelection::AudioRegionSelection (const AudioRegionSelection& other)
30 {
31
32         for (AudioRegionSelection::const_iterator i = other.begin(); i != other.end(); ++i) {
33                 add (*i, false);
34         }
35         _current_start = other._current_start;
36         _current_end = other._current_end;
37 }
38
39
40
41 AudioRegionSelection&
42 AudioRegionSelection::operator= (const AudioRegionSelection& other)
43 {
44         if (this != &other) {
45
46                 clear_all();
47                 
48                 for (AudioRegionSelection::const_iterator i = other.begin(); i != other.end(); ++i) {
49                         add (*i, false);
50                 }
51
52                 _current_start = other._current_start;
53                 _current_end = other._current_end;
54         }
55
56         return *this;
57 }
58
59 void
60 AudioRegionSelection::clear_all()
61 {
62         clear();
63         _bylayer.clear();
64 }
65
66 bool AudioRegionSelection::contains (AudioRegionView* rv)
67 {
68         if (this->find (rv) != end()) {
69                 return true;
70         }
71         else {
72                 return false;
73         }
74         
75 }
76
77 void
78 AudioRegionSelection::add (AudioRegionView* rv, bool dosort)
79 {
80         if (this->find (rv) != end()) {
81                 /* we already have it */
82                 return;
83         }
84
85         rv->AudioRegionViewGoingAway.connect (mem_fun(*this, &AudioRegionSelection::remove_it));
86
87         if (rv->region.first_frame() < _current_start || empty()) {
88                 _current_start = rv->region.first_frame();
89         }
90         
91         if (rv->region.last_frame() > _current_end || empty()) {
92                 _current_end = rv->region.last_frame();
93         }
94         
95         insert (rv);
96
97         // add to layer sorted list
98         add_to_layer (rv);
99         
100 }
101
102 void
103 AudioRegionSelection::remove_it (AudioRegionView *rv)
104 {
105         remove (rv);
106 }
107
108 bool
109 AudioRegionSelection::remove (AudioRegionView* rv)
110 {
111         AudioRegionSelection::iterator i;
112
113         if ((i = this->find (rv)) != end()) {
114
115                 erase (i);
116
117                 // remove from layer sorted list
118                 _bylayer.remove (rv);
119                 
120                 if (empty()) {
121
122                         _current_start = 0;
123                         _current_end = 0;
124
125                 } else {
126                         
127                         AudioRegion& region ((*i)->region);
128
129                         if (region.first_frame() == _current_start) {
130                                 
131                                 /* reset current start */
132                                 
133                                 jack_nframes_t ref = max_frames;
134                                 
135                                 for (i = begin (); i != end(); ++i) {
136                                         if (region.first_frame() < ref) {
137                                                 ref = region.first_frame();
138                                         }
139                                 }
140                                 
141                                 _current_start = ref;
142                                 
143                         }
144                         
145                         if (region.last_frame() == _current_end) {
146
147                                 /* reset current end */
148                                 
149                                 jack_nframes_t ref = 0;
150                                 
151                                 for (i = begin (); i != end(); ++i) {
152                                         if (region.first_frame() > ref) {
153                                                 ref = region.first_frame();
154                                         }
155                                 }
156                                 
157                                 _current_end = ref;
158                         }
159                 }
160
161                 return true;
162         }
163
164         return false;
165 }
166
167 void
168 AudioRegionSelection::add_to_layer (AudioRegionView * rv)
169 {
170         // insert it into layer sorted position
171
172         list<AudioRegionView*>::iterator i;
173
174         for (i = _bylayer.begin(); i != _bylayer.end(); ++i)
175         {
176                 if (rv->region.layer() < (*i)->region.layer()) {
177                         _bylayer.insert(i, rv);
178                         return;
179                 }
180         }
181
182         // insert at end if we get here
183         _bylayer.insert(i, rv);
184 }
185
186 struct RegionSortByTime {
187     bool operator() (const AudioRegionView* a, const AudioRegionView* b) {
188             return a->region.position() < b->region.position();
189     }
190 };
191
192
193 void
194 AudioRegionSelection::by_position (list<AudioRegionView*>& foo) const
195 {
196         list<AudioRegionView*>::const_iterator i;
197         RegionSortByTime sorter;
198
199         for (i = _bylayer.begin(); i != _bylayer.end(); ++i) {
200                 foo.push_back (*i);
201         }
202
203         foo.sort (sorter);
204         return;
205 }