ardour
marker.cc
Go to the documentation of this file.
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 "canvas/rectangle.h"
24 #include "canvas/container.h"
25 #include "canvas/line.h"
26 #include "canvas/polygon.h"
27 #include "canvas/text.h"
28 #include "canvas/canvas.h"
29 #include "canvas/scroll_group.h"
30 #include "canvas/debug.h"
31 
32 #include "ardour_ui.h"
33 /*
34  * ardour_ui.h include was moved to the top of the list
35  * due to a conflicting definition of 'Rect' between
36  * Apple's MacTypes.h and GTK.
37  */
38 
39 #include "marker.h"
40 #include "public_editor.h"
41 #include "utils.h"
42 #include "rgb_macros.h"
43 
44 #include <gtkmm2ext/utils.h>
45 
46 #include "i18n.h"
47 
48 using namespace std;
49 using namespace ARDOUR;
50 using namespace ARDOUR_UI_UTILS;
51 using namespace Gtkmm2ext;
52 
53 PBD::Signal1<void,Marker*> Marker::CatchDeletion;
54 
55 static double marker_height = 13.0;
56 
57 void Marker::setup_sizes(const double timebar_height)
58 {
59  marker_height = floor (timebar_height) - 2;
60 }
61 
62 Marker::Marker (PublicEditor& ed, ArdourCanvas::Container& parent, guint32 rgba, const string& annotation,
63  Type type, framepos_t frame, bool handle_events)
64 
65  : editor (ed)
66  , _parent (&parent)
67  , _track_canvas_line (0)
68  , _type (type)
69  , _selected (false)
70  , _shown (false)
71  , _line_shown (false)
72  , _color (rgba)
73  , _left_label_limit (DBL_MAX)
74  , _right_label_limit (DBL_MAX)
75  , _label_offset (0)
76 
77 {
78 
79  const double MH = marker_height - 1;
80  const double M3 = std::max(1.f, rintf(3.f * ARDOUR_UI::ui_scale));
81  const double M6 = std::max(2.f, rintf(6.f * ARDOUR_UI::ui_scale));
82 
83  /* Shapes we use:
84  *
85  * Mark:
86  *
87  * (0,0) -> (6,0)
88  * ^ |
89  * | V
90  * (0,MH*.4) (6,MH*.4)
91  * \ /
92  * (3,MH)
93  *
94  *
95  * TempoMark:
96  * MeterMark:
97  *
98  * (3,0)
99  * / \
100  * (0,MH*.6) (6,MH.*.6)
101  * ^ |
102  * | V
103  * (0,MH) <- (6,MH)
104  *
105  *
106  * SessionStart:
107  * RangeStart:
108  *
109  * 0,0\
110  * | \
111  * | \ 6,MH/2
112  * | /
113  * | /
114  * 0,MH
115  *
116  *
117  * SessionEnd:
118  * RangeEnd:
119  *
120  * /12,0
121  * / |
122  * 6,MH/2/ |
123  * \ |
124  * \ |
125  * \12,MH
126  *
127  *
128  * PunchIn:
129  *
130  * 0,0 ------> marker_height,0
131  * | /
132  * | /
133  * | /
134  * | /
135  * | /
136  * | /
137  * 0,marker_height
138  *
139  *
140  * PunchOut
141  *
142  * 0,0 ------> marker_height,0
143  * \ |
144  * \ |
145  * \ |
146  * \ |
147  * \ |
148  * \ |
149  * \ |
150  * marker_height,marker_height
151  *
152  */
153 
154  switch (type) {
155  case Mark:
156  points = new ArdourCanvas::Points ();
157 
158  points->push_back (ArdourCanvas::Duple (0.0, 0.0));
159  points->push_back (ArdourCanvas::Duple ( M6, 0.0));
160  points->push_back (ArdourCanvas::Duple ( M6, MH * .4));
161  points->push_back (ArdourCanvas::Duple ( M3, MH));
162  points->push_back (ArdourCanvas::Duple (0.0, MH * .4));
163  points->push_back (ArdourCanvas::Duple (0.0, 0.0));
164 
165  _shift = 3;
166  _label_offset = 10.0;
167  break;
168 
169  case Tempo:
170  case Meter:
171  points = new ArdourCanvas::Points ();
172  points->push_back (ArdourCanvas::Duple ( M3, 0.0));
173  points->push_back (ArdourCanvas::Duple ( M6, MH * .6));
174  points->push_back (ArdourCanvas::Duple ( M6, MH));
175  points->push_back (ArdourCanvas::Duple (0.0, MH));
176  points->push_back (ArdourCanvas::Duple (0.0, MH * .6));
177  points->push_back (ArdourCanvas::Duple ( M3, 0.0));
178 
179  _shift = 3;
180  _label_offset = 8.0;
181  break;
182 
183  case SessionStart:
184  case RangeStart:
185  points = new ArdourCanvas::Points ();
186  points->push_back (ArdourCanvas::Duple ( 0.0, 0.0));
187  points->push_back (ArdourCanvas::Duple (M6 + .5, MH * .5));
188  points->push_back (ArdourCanvas::Duple ( 0.0, MH));
189  points->push_back (ArdourCanvas::Duple ( 0.0, 0.0));
190 
191  _shift = 0;
192  _label_offset = 8.0;
193  break;
194 
195  case SessionEnd:
196  case RangeEnd:
197  points = new ArdourCanvas::Points ();
198  points->push_back (ArdourCanvas::Duple ( M6, 0.0));
199  points->push_back (ArdourCanvas::Duple ( M6, MH));
200  points->push_back (ArdourCanvas::Duple (0.0, MH * .5));
201  points->push_back (ArdourCanvas::Duple ( M6, 0.0));
202 
203  _shift = M6;
204  _label_offset = 0.0;
205  break;
206 
207  case LoopStart:
208  points = new ArdourCanvas::Points ();
209  points->push_back (ArdourCanvas::Duple (0.0, 0.0));
210  points->push_back (ArdourCanvas::Duple (marker_height, marker_height));
211  points->push_back (ArdourCanvas::Duple (0.0, marker_height));
212  points->push_back (ArdourCanvas::Duple (0.0, 0.0));
213 
214  _shift = 0;
216  break;
217 
218  case LoopEnd:
219  points = new ArdourCanvas::Points ();
220  points->push_back (ArdourCanvas::Duple (marker_height, 0.0));
221  points->push_back (ArdourCanvas::Duple (marker_height, marker_height));
222  points->push_back (ArdourCanvas::Duple (0.0, marker_height));
223  points->push_back (ArdourCanvas::Duple (marker_height, 0.0));
224 
226  _label_offset = 0.0;
227  break;
228 
229  case PunchIn:
230  points = new ArdourCanvas::Points ();
231  points->push_back (ArdourCanvas::Duple (0.0, 0.0));
232  points->push_back (ArdourCanvas::Duple (marker_height, 0.0));
233  points->push_back (ArdourCanvas::Duple (0.0, marker_height));
234  points->push_back (ArdourCanvas::Duple (0.0, 0.0));
235 
236  _shift = 0;
238  break;
239 
240  case PunchOut:
241  points = new ArdourCanvas::Points ();
242  points->push_back (ArdourCanvas::Duple (0.0, 0.0));
243  points->push_back (ArdourCanvas::Duple (marker_height, 0.0));
244  points->push_back (ArdourCanvas::Duple (marker_height, marker_height));
245  points->push_back (ArdourCanvas::Duple (0.0, 0.0));
246 
248  _label_offset = 0.0;
249  break;
250 
251  }
252 
253  frame_position = frame;
256 
257  group = new ArdourCanvas::Container (&parent, ArdourCanvas::Duple (unit_position, 0));
258 #ifdef CANVAS_DEBUG
259  group->name = string_compose ("Marker::group for %1", annotation);
260 #endif
261 
262  _name_background = new ArdourCanvas::Rectangle (group);
263 #ifdef CANVAS_DEBUG
264  _name_background->name = string_compose ("Marker::_name_background for %1", annotation);
265 #endif
266 
267  /* adjust to properly locate the tip */
268 
269  mark = new ArdourCanvas::Polygon (group);
270  CANVAS_DEBUG_NAME (mark, string_compose ("Marker::mark for %1", annotation));
271 
272  mark->set (*points);
273  set_color_rgba (rgba);
274 
275  /* setup name pixbuf sizes */
276  name_font = get_font_for_style (N_("MarkerText"));
277 
278  Gtk::Label foo;
279 
280  Glib::RefPtr<Pango::Layout> layout = foo.create_pango_layout (X_("Hg")); /* ascender + descender */
281  int width;
282 
283  layout->set_font_description (name_font);
285 
286  _name_item = new ArdourCanvas::Text (group);
287  CANVAS_DEBUG_NAME (_name_item, string_compose ("Marker::_name_item for %1", annotation));
288  _name_item->set_font_description (name_font);
289  _name_item->set_color (RGBA_TO_UINT (0,0,0,255));
290  _name_item->set_position (ArdourCanvas::Duple (_label_offset, (marker_height - name_height - 1) * .5 ));
291 
292  set_name (annotation.c_str());
293 
294  editor.ZoomChanged.connect (sigc::mem_fun (*this, &Marker::reposition));
295 
296  /* events will be handled by both the group and the mark itself, so
297  * make sure they can both be used to lookup this object.
298  */
299 
300  group->set_data ("marker", this);
301  mark->set_data ("marker", this);
302 
303  if (handle_events) {
304  group->Event.connect (sigc::bind (sigc::mem_fun (editor, &PublicEditor::canvas_marker_event), group, this));
305  }
306 }
307 
309 {
310  CatchDeletion (this); /* EMIT SIGNAL */
311 
312  /* destroying the parent group destroys its contents, namely any polygons etc. that we added */
313  delete group;
314  delete _track_canvas_line;
315 }
316 
317 void Marker::reparent(ArdourCanvas::Container & parent)
318 {
319  group->reparent (&parent);
320  _parent = &parent;
321 }
322 
323 void
325 {
326  _selected = s;
327  setup_line ();
328 }
329 
330 void
332 {
333  _line_shown = s;
334  setup_line ();
335 }
336 
337 void
339 {
340  if (_shown && (_selected || _line_shown)) {
341 
342  if (_track_canvas_line == 0) {
343 
344  _track_canvas_line = new ArdourCanvas::Line (editor.get_hscroll_group());
345  _track_canvas_line->set_outline_color (ARDOUR_UI::config()->color ("edit point"));
346  _track_canvas_line->Event.connect (sigc::bind (sigc::mem_fun (editor, &PublicEditor::canvas_marker_event), group, this));
347  }
348 
349  ArdourCanvas::Duple g = group->canvas_origin();
350  ArdourCanvas::Duple d = _track_canvas_line->canvas_to_item (ArdourCanvas::Duple (g.x + _shift, 0));
351 
352  _track_canvas_line->set_x0 (d.x);
353  _track_canvas_line->set_x1 (d.x);
354  _track_canvas_line->set_y0 (d.y);
355  _track_canvas_line->set_y1 (ArdourCanvas::COORD_MAX);
356  _track_canvas_line->set_outline_color (_selected ? ARDOUR_UI::config()->color ("edit point") : _color);
357  _track_canvas_line->raise_to_top ();
358  _track_canvas_line->show ();
359 
360  } else {
361  if (_track_canvas_line) {
362  _track_canvas_line->hide ();
363  }
364  }
365 }
366 
367 void
369 {
370  _canvas_height = h;
371  setup_line ();
372 }
373 
374 ArdourCanvas::Item&
376 {
377  return *group;
378 }
379 
380 void
381 Marker::set_name (const string& new_name)
382 {
383  _name = new_name;
384 
386 }
387 
389 bool
391 {
392  return (_type == SessionEnd || _type == RangeEnd || _type == LoopEnd || _type == PunchOut);
393 }
394 
395 void
397 {
398  double limit = DBL_MAX;
399 
400  if (label_on_left ()) {
401  limit = _left_label_limit;
402  } else {
403  limit = _right_label_limit;
404  }
405 
406  const float padding = std::max(2.f, rintf(2.f * ARDOUR_UI::ui_scale));
407 
408  /* Work out how wide the name can be */
409  int name_width = min ((double) pixel_width (_name, name_font) + padding, limit);
410 
411  if (name_width == 0) {
412  _name_item->hide ();
413  } else {
414  _name_item->show ();
415 
416  if (label_on_left ()) {
417  _name_item->set_x_position (-name_width);
418  }
419 
420  _name_item->clamp_width (name_width);
421  _name_item->set (_name);
422 
423  if (label_on_left ()) {
424  /* adjust right edge of background to fit text */
425  _name_background->set_x0 (_name_item->position().x - padding);
426  _name_background->set_x1 (_name_item->position().x + name_width + _shift);
427  } else {
428  /* right edge remains at zero (group-relative). Add
429  * arbitrary 2 pixels of extra padding at the end
430  */
431  _name_background->set_x1 (_name_item->position().x + name_width + padding);
432  }
433  }
434 
435  _name_background->set_y0 (0);
436  /* unfortunate hard coding - this has to * match the marker bars height */
437  _name_background->set_y1 (marker_height + 1.0);
438 }
439 
440 void
442 {
444  group->set_x_position (unit_position);
445  setup_line ();
446  frame_position = frame;
447 }
448 
449 void
451 {
453 }
454 
455 void
457 {
458  _shown = true;
459 
460  group->show ();
461  setup_line ();
462 }
463 
464 void
466 {
467  _shown = false;
468 
469  group->hide ();
470  setup_line ();
471 }
472 
473 void
475 {
476  _color = c;
477  mark->set_fill_color (_color);
478  mark->set_outline_color (_color);
479 
480  if (_track_canvas_line && !_selected) {
481  _track_canvas_line->set_outline_color (_color);
482  }
483 
484  _name_background->set_fill (true);
485  _name_background->set_fill_color (UINT_RGBA_CHANGE_A (_color, 0x70));
486  _name_background->set_outline_color (_color);
487 }
488 
490 void
492 {
493  /* Account for the size of the marker */
495  if (_left_label_limit < 0) {
496  _left_label_limit = 0;
497  }
498 
499  if (label_on_left ()) {
501  }
502 }
503 
505 void
507 {
508  /* Account for the size of the marker */
510  if (_right_label_limit < 0) {
511  _right_label_limit = 0;
512  }
513 
514  if (!label_on_left ()) {
516  }
517 }
518 
519 /***********************************************************************/
520 
521 TempoMarker::TempoMarker (PublicEditor& editor, ArdourCanvas::Container& parent, guint32 rgba, const string& text,
522  ARDOUR::TempoSection& temp)
523  : Marker (editor, parent, rgba, text, Tempo, 0, false),
524  _tempo (temp)
525 {
527  group->Event.connect (sigc::bind (sigc::mem_fun (editor, &PublicEditor::canvas_tempo_marker_event), group, this));
528 }
529 
531 {
532 }
533 
534 /***********************************************************************/
535 
536 MeterMarker::MeterMarker (PublicEditor& editor, ArdourCanvas::Container& parent, guint32 rgba, const string& text,
538  : Marker (editor, parent, rgba, text, Meter, 0, false),
539  _meter (m)
540 {
542  group->Event.connect (sigc::bind (sigc::mem_fun (editor, &PublicEditor::canvas_meter_marker_event), group, this));
543 }
544 
546 {
547 }
548 
void setup_name_display()
Definition: marker.cc:396
~TempoMarker()
Definition: marker.cc:530
session end
Definition: marker.h:49
ArdourCanvas::Points * points
Definition: marker.h:107
void set_left_label_limit(double)
Definition: marker.cc:491
void set_selected(bool)
Definition: marker.cc:324
void set_show_line(bool)
Definition: marker.cc:331
Pango::FontDescription get_font_for_style(std::string widgetname)
bool _line_shown
Definition: marker.h:119
void hide()
Definition: marker.cc:465
virtual bool canvas_tempo_marker_event(GdkEvent *event, ArdourCanvas::Item *, TempoMarker *)=0
Representation of the interface of the Editor class.
Definition: marker.h:41
MeterMarker(PublicEditor &editor, ArdourCanvas::Container &, guint32 rgba, const std::string &text, ARDOUR::MeterSection &)
Definition: marker.cc:536
tuple f
Definition: signals.py:35
Definition: Beats.hpp:239
virtual double sample_to_pixel(framepos_t frame) const =0
void show()
Definition: marker.cc:456
static PBD::Signal1< void, Marker * > CatchDeletion
Definition: marker.h:64
Pango::FontDescription name_font
Definition: marker.h:101
session start
Definition: marker.h:48
ARDOUR::MeterSection & _meter
Definition: marker.h:157
ArdourCanvas::Rectangle * _name_background
Definition: marker.h:109
#define UINT_RGBA_CHANGE_A(x, a)
Definition: rgb_macros.h:64
void reparent(ArdourCanvas::Container &parent)
Definition: marker.cc:317
virtual ArdourCanvas::ScrollGroup * get_hscroll_group() const =0
ArdourCanvas::Line * _track_canvas_line
Definition: marker.h:108
int name_height
Definition: marker.h:116
ArdourCanvas::Container * _parent
Definition: marker.h:103
#define X_(Text)
Definition: i18n.h:13
double _canvas_height
Definition: marker.h:120
virtual ~Marker()
Definition: marker.cc:308
framepos_t frame_position
Definition: marker.h:113
uint32_t _color
Definition: marker.h:121
void canvas_height_set(double)
Definition: marker.cc:368
void set_right_label_limit(double)
Definition: marker.cc:506
double _right_label_limit
the number of pixels available to the right of this marker for a label
Definition: marker.h:123
void set_color_rgba(uint32_t rgba)
Definition: marker.cc:474
Definition: amp.h:29
ArdourCanvas::Item & the_item() const
Definition: marker.cc:375
bool label_on_left() const
Definition: marker.cc:390
Type _type
Definition: marker.h:115
double _shift
Definition: marker.h:114
double _label_offset
Definition: marker.h:124
int64_t framepos_t
Definition: types.h:66
ArdourCanvas::Container * group
Definition: marker.h:104
std::string _name
Definition: marker.h:111
void set_position(framepos_t)
Definition: marker.cc:441
virtual bool canvas_marker_event(GdkEvent *event, ArdourCanvas::Item *, Marker *)=0
virtual bool canvas_meter_marker_event(GdkEvent *event, ArdourCanvas::Item *, MeterMarker *)=0
static void setup_sizes(const double timebar_height)
Definition: marker.cc:57
Marker(PublicEditor &editor, ArdourCanvas::Container &, guint32 rgba, const std::string &text, Type, framepos_t frame=0, bool handle_events=true)
LIBGTKMM2EXT_API void get_ink_pixel_size(Glib::RefPtr< Pango::Layout >, int &width, int &height)
Definition: utils.cc:51
ArdourCanvas::Polygon * mark
Definition: marker.h:105
static UIConfiguration * config()
Definition: ardour_ui.h:188
bool _shown
Definition: marker.h:118
bool _selected
Definition: marker.h:117
double unit_position
Definition: marker.h:112
sigc::signal< void > ZoomChanged
framepos_t frame() const
Definition: tempo.h:100
PublicEditor & editor
Definition: marker.h:99
double _left_label_limit
the number of pixels available to the left of this marker for a label
Definition: marker.h:122
void set_name(const std::string &)
Definition: marker.cc:381
LIBGTKMM2EXT_API int pixel_width(const std::string &str, Pango::FontDescription &font)
#define RGBA_TO_UINT(r, g, b, a)
Definition: rgb_macros.h:34
static float ui_scale
Definition: ardour_ui.h:189
TempoMarker(PublicEditor &editor, ArdourCanvas::Container &, guint32 rgba, const std::string &text, ARDOUR::TempoSection &)
Definition: marker.cc:521
~MeterMarker()
Definition: marker.cc:545
void setup_line()
Definition: marker.cc:338
void reposition()
Definition: marker.cc:450
ARDOUR::TempoSection & _tempo
Definition: marker.h:145
static double marker_height
Definition: marker.cc:55
std::string string_compose(const std::string &fmt, const T1 &o1)
Definition: compose.h:208
#define N_(Text)
Definition: i18n.h:12
ArdourCanvas::Text * _name_item
Definition: marker.h:106
LIBARDOUR_API PBD::PropertyDescriptor< bool > color
Definition: route_group.cc:50