0325bcfc31429aff8c6913f31863239567489c50
[ardour.git] / gtk2_ardour / marker.cc
1 /*
2     Copyright (C) 2001 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
20 #include <sigc++/bind.h>
21 #include <ardour/tempo.h>
22
23 #include "marker.h"
24 #include "public_editor.h"
25 #include "utils.h"
26 #include "canvas_impl.h"
27 #include "color.h"
28
29 #include "i18n.h"
30
31 using namespace ARDOUR;
32
33 Marker::Marker (PublicEditor& ed, ArdourCanvas::Group& parent, guint32 rgba, const string& annotation, 
34                 Type type, nframes_t frame, bool handle_events)
35
36         : editor (ed), _type(type)
37 {
38         double label_offset = 0;
39         bool annotate_left = false;
40
41         /* Shapes we use:
42
43           Mark:
44
45            (0,0) -> (6,0)
46              ^        |
47              |        V
48            (0,5)    (6,5)
49                \    / 
50                (3,10)
51
52
53            TempoMark:
54            MeterMark:
55
56                (3,0)
57               /      \
58            (0,5) -> (6,5)
59              ^        |
60              |        V
61            (0,10)<-(6,10)
62
63
64            Start:
65
66            0,0\ 
67             |  \        
68             |   \ 6,6
69             |   /
70             |  /
71            0,12 
72
73            End:
74
75                /12,0
76               /     | 
77              /      |
78            6,6      |
79              \      |
80               \     |
81                \    |
82                12,12
83
84              
85            TransportStart:
86
87              0,0
88               | \ 
89               |  \ 
90               |   \ 
91               |    \
92               |     \  
93              0,13 --- 13,13
94
95            TransportEnd:
96
97                     /13,0
98                    /   |
99                   /    |
100                  /     |
101                 /      |
102                /       |
103              0,13 ------ 13,13
104              
105
106              PunchIn:
107
108              0,0 ------> 13,0
109               |       /
110               |      /
111               |     /
112               |    / 
113               |   / 
114               |  / 
115              0,13
116
117              PunchOut
118
119            0,0 -->-13,0
120             \       | 
121              \      |
122               \     |
123                \    |
124                 \   |
125                  \  |
126                  13,13
127              
128            
129         */
130
131         switch (type) {
132         case Mark:
133                 points = new ArdourCanvas::Points ();
134
135                 points->push_back (Gnome::Art::Point (0.0, 0.0));
136                 points->push_back (Gnome::Art::Point (6.0, 0.0));
137                 points->push_back (Gnome::Art::Point (6.0, 5.0));
138                 points->push_back (Gnome::Art::Point (3.0, 10.0));              
139                 points->push_back (Gnome::Art::Point (0.0, 5.0));               
140                 points->push_back (Gnome::Art::Point (0.0, 0.0));               
141                 
142                 shift = 3;
143                 label_offset = 8.0;
144                 break;
145
146         case Tempo:
147         case Meter:
148
149                 points = new ArdourCanvas::Points ();
150                 points->push_back (Gnome::Art::Point (3.0, 0.0));
151                 points->push_back (Gnome::Art::Point (6.0, 5.0));               
152                 points->push_back (Gnome::Art::Point (6.0, 10.0));              
153                 points->push_back (Gnome::Art::Point (0.0, 10.0));              
154                 points->push_back (Gnome::Art::Point (0.0, 5.0));               
155                 points->push_back (Gnome::Art::Point (3.0, 0.0));               
156
157                 shift = 3;
158                 label_offset = 8.0;
159                 break;
160
161         case Start:
162                 points = new ArdourCanvas::Points ();
163                 points->push_back (Gnome::Art::Point (0.0, 0.0));               
164                 points->push_back (Gnome::Art::Point (6.5, 6.5));               
165                 points->push_back (Gnome::Art::Point (0.0, 13.0));              
166                 points->push_back (Gnome::Art::Point (0.0, 0.0));       
167
168                 shift = 0;
169                 label_offset = 13.0;
170                 break;
171
172         case End:
173                 points = new ArdourCanvas::Points ();
174                 points->push_back (Gnome::Art::Point (6.5, 6.5));
175                 points->push_back (Gnome::Art::Point (13.0, 0.0));              
176                 points->push_back (Gnome::Art::Point (13.0, 13.0));                     
177                 points->push_back (Gnome::Art::Point (6.5, 6.5));               
178                 
179                 shift = 13;
180                 label_offset = 6.0;
181                 annotate_left = true;
182                 break;
183
184         case LoopStart:
185                 points = new ArdourCanvas::Points ();
186                 points->push_back (Gnome::Art::Point (0.0, 0.0));       
187                 points->push_back (Gnome::Art::Point (13.0, 13.0));             
188                 points->push_back (Gnome::Art::Point (0.0, 13.0));              
189                 points->push_back (Gnome::Art::Point (0.0, 0.0));               
190                 
191                 shift = 0;
192                 label_offset = 12.0;
193                 break;
194
195         case LoopEnd:
196                 points = new ArdourCanvas::Points ();
197                 points->push_back (Gnome::Art::Point (13.0,  0.0));
198                 points->push_back (Gnome::Art::Point (13.0, 13.0));     
199                 points->push_back (Gnome::Art::Point (0.0, 13.0));              
200                 points->push_back (Gnome::Art::Point (13.0, 0.0));
201                 
202                 shift = 13;
203                 label_offset = 0.0;
204                 annotate_left = true;
205                 break;
206
207         case  PunchIn:
208                 points = new ArdourCanvas::Points ();
209                 points->push_back (Gnome::Art::Point (0.0, 0.0));
210                 points->push_back (Gnome::Art::Point (13.0, 0.0));              
211                 points->push_back (Gnome::Art::Point (0.0, 13.0));      
212                 points->push_back (Gnome::Art::Point (0.0, 0.0));       
213
214                 shift = 0;
215                 label_offset = 13.0;
216                 break;
217                 
218         case  PunchOut:
219                 points = new ArdourCanvas::Points ();
220                 points->push_back (Gnome::Art::Point (0.0, 0.0));
221                 points->push_back (Gnome::Art::Point (12.0, 0.0));                      
222                 points->push_back (Gnome::Art::Point (12.0, 12.0));             
223                 points->push_back (Gnome::Art::Point (0.0, 0.0));               
224
225                 shift = 13;
226                 label_offset = 0.0;
227                 annotate_left = true;
228                 break;
229                 
230         }
231
232         frame_position = frame;
233         unit_position = editor.frame_to_unit (frame);
234
235         /* adjust to properly locate the tip */
236
237         unit_position -= shift;
238
239         group = new Group (parent, unit_position, 1.0);
240
241         mark = new Polygon (*group);
242         mark->property_points() = *points;
243         mark->property_fill_color_rgba() = rgba;
244         mark->property_outline_color_rgba() = rgba;
245         mark->property_width_pixels() = 1;
246         Pango::FontDescription font = get_font_for_style (N_("MarkerText"));
247         
248         text = new Text (*group);
249         text->property_text() = annotation.c_str();
250         text->property_font_desc() = font;
251         if (annotate_left) {
252           text->property_x() = -(text->property_text_width());
253         } else {
254           text->property_x() = label_offset;
255         }
256         text->property_y() = 0.0;
257         text->property_anchor() = Gtk::ANCHOR_NW;
258         text->property_fill_color_rgba() = Config->canvasvar_MarkerLabel.get();
259
260         editor.ZoomChanged.connect (mem_fun (*this, &Marker::reposition));
261
262         mark->set_data ("marker", this);
263
264         if (handle_events) {
265                 group->signal_event().connect (bind (mem_fun (editor, &PublicEditor::canvas_marker_event), mark, this));
266         }
267
268 }
269
270 Marker::~Marker ()
271 {
272         /* destroying the parent group destroys its contents, namely any polygons etc. that we added */
273         delete text;
274         delete mark;
275         delete points;
276 }
277
278 ArdourCanvas::Item&
279 Marker::the_item() const
280 {
281         return *mark;
282 }
283
284 void
285 Marker::set_name (const string& name)
286 {
287         text->property_text() = name.c_str();
288         if (_type == End) {
289           text->property_x() = -(text->property_text_width());
290         }
291 }
292
293 void
294 Marker::set_position (nframes_t frame)
295 {
296         double new_unit_position = editor.frame_to_unit (frame);
297         new_unit_position -= shift;
298         group->move (new_unit_position - unit_position, 0.0);
299         frame_position = frame;
300         unit_position = new_unit_position;
301 }
302
303 void
304 Marker::reposition ()
305 {
306         set_position (frame_position);
307 }       
308
309 void
310 Marker::show ()
311 {
312         group->show();
313 }
314
315 void
316 Marker::hide ()
317 {
318         group->hide();
319 }
320
321 void
322 Marker::set_color_rgba (uint32_t color)
323 {
324         mark->property_fill_color_rgba() = color;
325 }
326
327 /***********************************************************************/
328
329 TempoMarker::TempoMarker (PublicEditor& editor, ArdourCanvas::Group& parent, guint32 rgba, const string& text, 
330                           ARDOUR::TempoSection& temp)
331         : Marker (editor, parent, rgba, text, Tempo, 0, false),
332           _tempo (temp)
333 {
334         set_position (_tempo.frame());
335         group->signal_event().connect (bind (mem_fun (editor, &PublicEditor::canvas_tempo_marker_event), mark, this));
336 }
337
338 TempoMarker::~TempoMarker ()
339 {
340 }
341
342 /***********************************************************************/
343
344 MeterMarker::MeterMarker (PublicEditor& editor, ArdourCanvas::Group& parent, guint32 rgba, const string& text, 
345                           ARDOUR::MeterSection& m) 
346         : Marker (editor, parent, rgba, text, Meter, 0, false),
347           _meter (m)
348 {
349         set_position (_meter.frame());
350         group->signal_event().connect (bind (mem_fun (editor, &PublicEditor::canvas_meter_marker_event), mark, this));
351 }
352
353 MeterMarker::~MeterMarker ()
354 {
355 }
356