fix for vamp-sdk botch in SConstruct; new audio clock focus command; make insert...
[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 "ardour_ui.h"
28
29 #include "i18n.h"
30
31 Marker::Marker (PublicEditor& ed, ArdourCanvas::Group& parent, guint32 rgba, const string& annotation, 
32                 Type type, nframes_t frame, bool handle_events)
33
34         : editor (ed), _parent(&parent), _type(type)
35 {
36         double label_offset = 0;
37         bool annotate_left = false;
38
39         /* Shapes we use:
40
41           Mark:
42
43            (0,0) -> (6,0)
44              ^        |
45              |        V
46            (0,5)    (6,5)
47                \    / 
48                (3,10)
49
50
51            TempoMark:
52            MeterMark:
53
54                (3,0)
55               /      \
56            (0,5) -> (6,5)
57              ^        |
58              |        V
59            (0,10)<-(6,10)
60
61
62            Start:
63
64            0,0\ 
65             |  \        
66             |   \ 6,6
67             |   /
68             |  /
69            0,12 
70
71            End:
72
73                /12,0
74               /     | 
75              /      |
76            6,6      |
77              \      |
78               \     |
79                \    |
80                12,12
81
82              
83            TransportStart:
84
85              0,0
86               | \ 
87               |  \ 
88               |   \ 
89               |    \
90               |     \  
91              0,13 --- 13,13
92
93            TransportEnd:
94
95                     /13,0
96                    /   |
97                   /    |
98                  /     |
99                 /      |
100                /       |
101              0,13 ------ 13,13
102              
103
104              PunchIn:
105
106              0,0 ------> 13,0
107               |       /
108               |      /
109               |     /
110               |    / 
111               |   / 
112               |  / 
113              0,13
114
115              PunchOut
116
117            0,0 -->-13,0
118             \       | 
119              \      |
120               \     |
121                \    |
122                 \   |
123                  \  |
124                  13,13
125              
126            
127         */
128
129         switch (type) {
130         case Mark:
131                 points = new ArdourCanvas::Points ();
132
133                 points->push_back (Gnome::Art::Point (0.0, 0.0));
134                 points->push_back (Gnome::Art::Point (6.0, 0.0));
135                 points->push_back (Gnome::Art::Point (6.0, 5.0));
136                 points->push_back (Gnome::Art::Point (3.0, 10.0));              
137                 points->push_back (Gnome::Art::Point (0.0, 5.0));               
138                 points->push_back (Gnome::Art::Point (0.0, 0.0));               
139                 
140                 shift = 3;
141                 label_offset = 8.0;
142                 break;
143
144         case Tempo:
145         case Meter:
146
147                 points = new ArdourCanvas::Points ();
148                 points->push_back (Gnome::Art::Point (3.0, 0.0));
149                 points->push_back (Gnome::Art::Point (6.0, 5.0));               
150                 points->push_back (Gnome::Art::Point (6.0, 10.0));              
151                 points->push_back (Gnome::Art::Point (0.0, 10.0));              
152                 points->push_back (Gnome::Art::Point (0.0, 5.0));               
153                 points->push_back (Gnome::Art::Point (3.0, 0.0));               
154
155                 shift = 3;
156                 label_offset = 8.0;
157                 break;
158
159         case Start:
160                 points = new ArdourCanvas::Points ();
161                 points->push_back (Gnome::Art::Point (0.0, 0.0));               
162                 points->push_back (Gnome::Art::Point (6.5, 6.5));               
163                 points->push_back (Gnome::Art::Point (0.0, 13.0));              
164                 points->push_back (Gnome::Art::Point (0.0, 0.0));       
165
166                 shift = 0;
167                 label_offset = 13.0;
168                 break;
169
170         case End:
171                 points = new ArdourCanvas::Points ();
172                 points->push_back (Gnome::Art::Point (6.5, 6.5));
173                 points->push_back (Gnome::Art::Point (13.0, 0.0));              
174                 points->push_back (Gnome::Art::Point (13.0, 13.0));                     
175                 points->push_back (Gnome::Art::Point (6.5, 6.5));               
176                 
177                 shift = 13;
178                 label_offset = 6.0;
179                 annotate_left = true;
180                 break;
181
182         case LoopStart:
183                 points = new ArdourCanvas::Points ();
184                 points->push_back (Gnome::Art::Point (0.0, 0.0));       
185                 points->push_back (Gnome::Art::Point (13.0, 13.0));             
186                 points->push_back (Gnome::Art::Point (0.0, 13.0));              
187                 points->push_back (Gnome::Art::Point (0.0, 0.0));               
188                 
189                 shift = 0;
190                 label_offset = 12.0;
191                 break;
192
193         case LoopEnd:
194                 points = new ArdourCanvas::Points ();
195                 points->push_back (Gnome::Art::Point (13.0,  0.0));
196                 points->push_back (Gnome::Art::Point (13.0, 13.0));     
197                 points->push_back (Gnome::Art::Point (0.0, 13.0));              
198                 points->push_back (Gnome::Art::Point (13.0, 0.0));
199                 
200                 shift = 13;
201                 label_offset = 0.0;
202                 annotate_left = true;
203                 break;
204
205         case  PunchIn:
206                 points = new ArdourCanvas::Points ();
207                 points->push_back (Gnome::Art::Point (0.0, 0.0));
208                 points->push_back (Gnome::Art::Point (13.0, 0.0));              
209                 points->push_back (Gnome::Art::Point (0.0, 13.0));      
210                 points->push_back (Gnome::Art::Point (0.0, 0.0));       
211
212                 shift = 0;
213                 label_offset = 13.0;
214                 break;
215                 
216         case  PunchOut:
217                 points = new ArdourCanvas::Points ();
218                 points->push_back (Gnome::Art::Point (0.0, 0.0));
219                 points->push_back (Gnome::Art::Point (12.0, 0.0));                      
220                 points->push_back (Gnome::Art::Point (12.0, 12.0));             
221                 points->push_back (Gnome::Art::Point (0.0, 0.0));               
222
223                 shift = 13;
224                 label_offset = 0.0;
225                 annotate_left = true;
226                 break;
227                 
228         }
229
230         frame_position = frame;
231         unit_position = editor.frame_to_unit (frame);
232
233         /* adjust to properly locate the tip */
234
235         unit_position -= shift;
236
237         group = new Group (parent, unit_position, 1.0);
238
239         mark = new Polygon (*group);
240         mark->property_points() = *points;
241         mark->property_fill_color_rgba() = rgba;
242         mark->property_outline_color_rgba() = rgba;
243         mark->property_width_pixels() = 1;
244         Pango::FontDescription* font = get_font_for_style (N_("MarkerText"));
245         
246         text = new Text (*group);
247         text->property_text() = annotation.c_str();
248         text->property_font_desc() = *font;
249
250         delete font;
251         
252         if (annotate_left) {
253                 text->property_x() = -(text->property_text_width());
254         } else {
255                 text->property_x() = label_offset;
256         }
257         text->property_y() = 0.0;
258         text->property_anchor() = Gtk::ANCHOR_NW;
259         text->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_MarkerLabel.get();
260
261         editor.ZoomChanged.connect (mem_fun (*this, &Marker::reposition));
262
263         mark->set_data ("marker", this);
264
265         if (handle_events) {
266                 group->signal_event().connect (bind (mem_fun (editor, &PublicEditor::canvas_marker_event), mark, this));
267         }
268
269         line = 0;
270         line_points = 0;
271
272 }
273
274
275 Marker::~Marker ()
276 {
277         drop_references ();
278
279         /* destroying the parent group destroys its contents, namely any polygons etc. that we added */
280         delete text;
281         delete mark;
282         delete points;
283
284         if (line) {
285                 delete line;
286                 delete line_points;
287         }
288 }
289
290 void Marker::reparent(ArdourCanvas::Group & parent)
291 {
292         group->reparent(parent);
293         _parent = &parent;
294 }
295
296 void
297 Marker::add_line (ArdourCanvas::Group* group, double initial_height)
298 {
299         if (!line) {
300
301                 line_points = new ArdourCanvas::Points ();
302                 line_points->push_back (Gnome::Art::Point (unit_position + shift, 0.0));
303                 line_points->push_back (Gnome::Art::Point (unit_position + shift, initial_height));                     
304                 
305                 line = new ArdourCanvas::Line (*group);
306                 line->property_width_pixels() = 1;
307                 line->property_points() = *line_points;
308                 line->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_EditPoint.get();
309 #if 0
310                 line->property_first_arrowhead() = TRUE;
311                 line->property_last_arrowhead() = TRUE;
312                 line->property_arrow_shape_a() = 11.0;
313                 line->property_arrow_shape_b() = 0.0;
314                 line->property_arrow_shape_c() = 9.0;
315 #endif
316                 line->signal_event().connect (bind (mem_fun (editor, &PublicEditor::canvas_marker_event), mark, this));
317         }
318
319         show_line ();
320 }
321
322 void
323 Marker::show_line ()
324 {
325         if (line) {
326                 line->raise_to_top();
327                 line->show ();
328         }
329 }
330
331 void 
332 Marker::hide_line ()
333 {
334         if (line) {
335                 line->hide ();
336         }
337 }
338
339 ArdourCanvas::Item&
340 Marker::the_item() const
341 {
342         return *mark;
343 }
344
345 void
346 Marker::set_name (const string& name)
347 {
348         text->property_text() = name.c_str();
349         if (_type == End) {
350           text->property_x() = -(text->property_text_width());
351         }
352 }
353
354 void
355 Marker::set_position (nframes_t frame)
356 {
357         double new_unit_position = editor.frame_to_unit (frame);
358         new_unit_position -= shift;
359         group->move (new_unit_position - unit_position, 0.0);
360         frame_position = frame;
361         unit_position = new_unit_position;
362
363         if (line) {
364                 (*line_points)[0].set_x (unit_position + shift);
365                 (*line_points)[1].set_x (unit_position + shift);
366                 line->property_points() = *line_points;
367         }
368 }
369
370 void
371 Marker::reposition ()
372 {
373         set_position (frame_position);
374 }       
375
376 void
377 Marker::show ()
378 {
379         group->show();
380 }
381
382 void
383 Marker::hide ()
384 {
385         group->hide();
386 }
387
388 void
389 Marker::set_color_rgba (uint32_t color)
390 {
391         mark->property_fill_color_rgba() = color;
392         mark->property_outline_color_rgba() = color;
393 }
394
395 /***********************************************************************/
396
397 TempoMarker::TempoMarker (PublicEditor& editor, ArdourCanvas::Group& parent, guint32 rgba, const string& text, 
398                           ARDOUR::TempoSection& temp)
399         : Marker (editor, parent, rgba, text, Tempo, 0, false),
400           _tempo (temp)
401 {
402         set_position (_tempo.frame());
403         group->signal_event().connect (bind (mem_fun (editor, &PublicEditor::canvas_tempo_marker_event), mark, this));
404 }
405
406 TempoMarker::~TempoMarker ()
407 {
408 }
409
410 /***********************************************************************/
411
412 MeterMarker::MeterMarker (PublicEditor& editor, ArdourCanvas::Group& parent, guint32 rgba, const string& text, 
413                           ARDOUR::MeterSection& m) 
414         : Marker (editor, parent, rgba, text, Meter, 0, false),
415           _meter (m)
416 {
417         set_position (_meter.frame());
418         group->signal_event().connect (bind (mem_fun (editor, &PublicEditor::canvas_meter_marker_event), mark, this));
419 }
420
421 MeterMarker::~MeterMarker ()
422 {
423 }
424