Merge libs/ardour and gtk2_ardour with 2.0-ongoing R2837.
[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 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), _parent(&parent), _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
252         delete font;
253         
254         if (annotate_left) {
255                 text->property_x() = -(text->property_text_width());
256         } else {
257                 text->property_x() = label_offset;
258         }
259         text->property_y() = 0.0;
260         text->property_anchor() = Gtk::ANCHOR_NW;
261         text->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_MarkerLabel.get();
262
263         editor.ZoomChanged.connect (mem_fun (*this, &Marker::reposition));
264
265         mark->set_data ("marker", this);
266
267         if (handle_events) {
268                 group->signal_event().connect (bind (mem_fun (editor, &PublicEditor::canvas_marker_event), mark, this));
269         }
270
271         line = 0;
272         line_points = 0;
273
274 }
275
276
277 Marker::~Marker ()
278 {
279         drop_references ();
280
281         /* destroying the parent group destroys its contents, namely any polygons etc. that we added */
282         delete text;
283         delete mark;
284         delete points;
285
286         if (line) {
287                 delete line;
288                 delete line_points;
289         }
290 }
291
292 void Marker::reparent(ArdourCanvas::Group & parent)
293 {
294         group->reparent(parent);
295         _parent = &parent;
296 }
297
298 void
299 Marker::set_line_length (double len)
300 {
301         if (line) {
302                 line_points->back().set_y (len);
303                 line->property_points() = *line_points;
304         }
305 }
306
307 void
308 Marker::add_line (ArdourCanvas::Group* group, double initial_height)
309 {
310         if (!line) {
311
312                 line_points = new ArdourCanvas::Points ();
313                 line_points->push_back (Gnome::Art::Point (unit_position + shift, 0.0));
314                 line_points->push_back (Gnome::Art::Point (unit_position + shift, initial_height));                     
315                 
316                 line = new ArdourCanvas::Line (*group);
317                 line->property_width_pixels() = 1;
318                 line->property_points() = *line_points;
319                 line->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_EditPoint.get();
320 #if 0
321                 line->property_first_arrowhead() = TRUE;
322                 line->property_last_arrowhead() = TRUE;
323                 line->property_arrow_shape_a() = 11.0;
324                 line->property_arrow_shape_b() = 0.0;
325                 line->property_arrow_shape_c() = 9.0;
326 #endif
327                 line->signal_event().connect (bind (mem_fun (editor, &PublicEditor::canvas_marker_event), mark, this));
328         }
329
330         show_line ();
331 }
332
333 void
334 Marker::show_line ()
335 {
336         if (line) {
337                 line->raise_to_top();
338                 line->show ();
339         }
340 }
341
342 void 
343 Marker::hide_line ()
344 {
345         if (line) {
346                 line->hide ();
347         }
348 }
349
350 ArdourCanvas::Item&
351 Marker::the_item() const
352 {
353         return *mark;
354 }
355
356 void
357 Marker::set_name (const string& name)
358 {
359         text->property_text() = name.c_str();
360         if (_type == End) {
361           text->property_x() = -(text->property_text_width());
362         }
363 }
364
365 void
366 Marker::set_position (nframes_t frame)
367 {
368         double new_unit_position = editor.frame_to_unit (frame);
369         new_unit_position -= shift;
370         group->move (new_unit_position - unit_position, 0.0);
371         frame_position = frame;
372         unit_position = new_unit_position;
373
374         if (line) {
375                 (*line_points)[0].set_x (unit_position + shift);
376                 (*line_points)[1].set_x (unit_position + shift);
377                 line->property_points() = *line_points;
378         }
379 }
380
381 void
382 Marker::reposition ()
383 {
384         set_position (frame_position);
385 }       
386
387 void
388 Marker::show ()
389 {
390         group->show();
391 }
392
393 void
394 Marker::hide ()
395 {
396         group->hide();
397 }
398
399 void
400 Marker::set_color_rgba (uint32_t color)
401 {
402         mark->property_fill_color_rgba() = color;
403         mark->property_outline_color_rgba() = color;
404 }
405
406 /***********************************************************************/
407
408 TempoMarker::TempoMarker (PublicEditor& editor, ArdourCanvas::Group& parent, guint32 rgba, const string& text, 
409                           ARDOUR::TempoSection& temp)
410         : Marker (editor, parent, rgba, text, Tempo, 0, false),
411           _tempo (temp)
412 {
413         set_position (_tempo.frame());
414         group->signal_event().connect (bind (mem_fun (editor, &PublicEditor::canvas_tempo_marker_event), mark, this));
415 }
416
417 TempoMarker::~TempoMarker ()
418 {
419 }
420
421 /***********************************************************************/
422
423 MeterMarker::MeterMarker (PublicEditor& editor, ArdourCanvas::Group& parent, guint32 rgba, const string& text, 
424                           ARDOUR::MeterSection& m) 
425         : Marker (editor, parent, rgba, text, Meter, 0, false),
426           _meter (m)
427 {
428         set_position (_meter.frame());
429         group->signal_event().connect (bind (mem_fun (editor, &PublicEditor::canvas_meter_marker_event), mark, this));
430 }
431
432 MeterMarker::~MeterMarker ()
433 {
434 }
435