ardour
editor_markers.cc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2000 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 <cstdlib>
21 #include <cmath>
22 
23 #include <gtkmm2ext/gtk_ui.h>
24 
25 #include "ardour/session.h"
26 #include "ardour/location.h"
27 #include "ardour/profile.h"
28 #include "pbd/memento_command.h"
29 
30 #include "canvas/canvas.h"
31 #include "canvas/item.h"
32 #include "canvas/rectangle.h"
33 
34 #include "editor.h"
35 #include "marker.h"
36 #include "selection.h"
37 #include "editing.h"
38 #include "gui_thread.h"
39 #include "actions.h"
40 #include "prompter.h"
41 #include "editor_drag.h"
42 
43 #include "i18n.h"
44 
45 using namespace std;
46 using namespace ARDOUR;
47 using namespace PBD;
48 using namespace Gtk;
49 using namespace Gtkmm2ext;
50 
51 void
53 {
54  for (LocationMarkerMap::iterator i = location_markers.begin(); i != location_markers.end(); ++i) {
55  delete i->second;
56  }
57 
58  location_markers.clear ();
59  _sorted_marker_lists.clear ();
60 }
61 
62 void
64 {
65  ENSURE_GUI_THREAD (*this, &Editor::add_new_location, location);
66 
67  ArdourCanvas::Container* group = add_new_location_internal (location);
68 
69  /* Do a full update of the markers in this group */
70  update_marker_labels (group);
71 
72  if (location->is_auto_punch()) {
73  update_punch_range_view ();
74  }
75 
76  if (location->is_auto_loop()) {
77  update_loop_range_view ();
78  }
79 }
80 
85 ArdourCanvas::Container*
87 {
89  uint32_t color;
90 
91  /* make a note here of which group this marker ends up in */
92  ArdourCanvas::Container* group = 0;
93 
94  if (location->is_cd_marker()) {
95  color = location_cd_marker_color;
96  } else if (location->is_mark()) {
97  color = location_marker_color;
98  } else if (location->is_auto_loop()) {
99  color = location_loop_color;
100  } else if (location->is_auto_punch()) {
101  color = location_punch_color;
102  } else {
103  color = location_range_color;
104  }
105 
106  if (location->is_mark()) {
107 
108  if (location->is_cd_marker() && ruler_cd_marker_action->get_active()) {
109  lam->start = new Marker (*this, *cd_marker_group, color, location->name(), Marker::Mark, location->start());
110  group = cd_marker_group;
111  } else {
112  lam->start = new Marker (*this, *marker_group, color, location->name(), Marker::Mark, location->start());
113  group = marker_group;
114  }
115 
116  lam->end = 0;
117 
118  } else if (location->is_auto_loop()) {
119 
120  // transport marker
121  lam->start = new Marker (*this, *transport_marker_group, color,
122  location->name(), Marker::LoopStart, location->start());
123  lam->end = new Marker (*this, *transport_marker_group, color,
124  location->name(), Marker::LoopEnd, location->end());
125  group = transport_marker_group;
126 
127  } else if (location->is_auto_punch()) {
128 
129  // transport marker
130  lam->start = new Marker (*this, *transport_marker_group, color,
131  location->name(), Marker::PunchIn, location->start());
132  lam->end = new Marker (*this, *transport_marker_group, color,
133  location->name(), Marker::PunchOut, location->end());
134  group = transport_marker_group;
135 
136  } else if (location->is_session_range()) {
137 
138  // session range
139  lam->start = new Marker (*this, *marker_group, color, _("start"), Marker::SessionStart, location->start());
140  lam->end = new Marker (*this, *marker_group, color, _("end"), Marker::SessionEnd, location->end());
141  group = marker_group;
142 
143  } else {
144  // range marker
145  if (location->is_cd_marker() && ruler_cd_marker_action->get_active()) {
146  lam->start = new Marker (*this, *cd_marker_group, color,
147  location->name(), Marker::RangeStart, location->start());
148  lam->end = new Marker (*this, *cd_marker_group, color,
149  location->name(), Marker::RangeEnd, location->end());
150  group = cd_marker_group;
151  } else {
152  lam->start = new Marker (*this, *range_marker_group, color,
153  location->name(), Marker::RangeStart, location->start());
154  lam->end = new Marker (*this, *range_marker_group, color,
155  location->name(), Marker::RangeEnd, location->end());
156  group = range_marker_group;
157  }
158  }
159 
160  if (location->is_hidden ()) {
161  lam->hide();
162  } else {
163  lam->show ();
164  }
165 
166  location->name_changed.connect (*this, invalidator (*this), boost::bind (&Editor::location_changed, this, _1), gui_context());
167  location->FlagsChanged.connect (*this, invalidator (*this), boost::bind (&Editor::location_flags_changed, this, location), gui_context());
168 
169  pair<Location*,LocationMarkers*> newpair;
170 
171  newpair.first = location;
172  newpair.second = lam;
173 
174  location_markers.insert (newpair);
175 
176  if (select_new_marker && location->is_mark()) {
177  selection->set (lam->start);
178  select_new_marker = false;
179  }
180 
181  lam->canvas_height_set (_visible_canvas_height);
182  lam->set_show_lines (_show_marker_lines);
183 
184  /* Add these markers to the appropriate sorted marker lists, which will render
185  them unsorted until a call to update_marker_labels() sorts them out.
186  */
187  _sorted_marker_lists[group].push_back (lam->start);
188  if (lam->end) {
189  _sorted_marker_lists[group].push_back (lam->end);
190  }
191 
192  return group;
193 }
194 
195 void
197 {
198  ENSURE_GUI_THREAD (*this, &Editor::location_changed, location)
199 
200  LocationMarkers *lam = find_location_markers (location);
201 
202  if (lam == 0) {
203  /* a location that isn't "marked" with markers */
204  return;
205  }
206 
207  lam->set_name (location->name ());
208  lam->set_position (location->start(), location->end());
209 
210  if (location->is_auto_loop()) {
211  update_loop_range_view ();
212  } else if (location->is_auto_punch()) {
213  update_punch_range_view ();
214  }
215 
216  check_marker_label (lam->start);
217  if (lam->end) {
218  check_marker_label (lam->end);
219  }
220 }
221 
226 void
228 {
229  /* Get a time-ordered list of markers from the last time anything changed */
230  std::list<Marker*>& sorted = _sorted_marker_lists[m->get_parent()];
231 
232  list<Marker*>::iterator i = find (sorted.begin(), sorted.end(), m);
233 
234  list<Marker*>::iterator prev = sorted.end ();
235  list<Marker*>::iterator next = i;
236  ++next;
237 
238  /* Look to see if the previous marker is still behind `m' in time */
239  if (i != sorted.begin()) {
240 
241  prev = i;
242  --prev;
243 
244  if ((*prev)->position() > m->position()) {
245  /* This marker is no longer in the correct order with the previous one, so
246  * update all the markers in this group.
247  */
248  update_marker_labels (m->get_parent ());
249  return;
250  }
251  }
252 
253  /* Look to see if the next marker is still ahead of `m' in time */
254  if (next != sorted.end() && (*next)->position() < m->position()) {
255  /* This marker is no longer in the correct order with the next one, so
256  * update all the markers in this group.
257  */
258  update_marker_labels (m->get_parent ());
259  return;
260  }
261 
262  if (prev != sorted.end()) {
263 
264  /* Update just the available space between the previous marker and this one */
265 
266  double const p = sample_to_pixel (m->position() - (*prev)->position());
267 
268  if (m->label_on_left()) {
269  (*prev)->set_right_label_limit (p / 2);
270  } else {
271  (*prev)->set_right_label_limit (p);
272  }
273 
274  if ((*prev)->label_on_left ()) {
275  m->set_left_label_limit (p);
276  } else {
277  m->set_left_label_limit (p / 2);
278  }
279  }
280 
281  if (next != sorted.end()) {
282 
283  /* Update just the available space between this marker and the next */
284 
285  double const p = sample_to_pixel ((*next)->position() - m->position());
286 
287  if ((*next)->label_on_left()) {
288  m->set_right_label_limit (p / 2);
289  } else {
290  m->set_right_label_limit (p);
291  }
292 
293  if (m->label_on_left()) {
294  (*next)->set_left_label_limit (p);
295  } else {
296  (*next)->set_left_label_limit (p / 2);
297  }
298  }
299 }
300 
302  bool operator() (Marker const * a, Marker const * b) {
303  return a->position() < b->position();
304  }
305 };
306 
308 void
310 {
311  for (std::map<ArdourCanvas::Container *, std::list<Marker *> >::iterator i = _sorted_marker_lists.begin(); i != _sorted_marker_lists.end(); ++i) {
312  update_marker_labels (i->first);
313  }
314 }
315 
317 void
318 Editor::update_marker_labels (ArdourCanvas::Container* group)
319 {
320  list<Marker*>& sorted = _sorted_marker_lists[group];
321 
322  if (sorted.empty()) {
323  return;
324  }
325 
326  /* We sort the list of markers and then set up the space available between each one */
327 
328  sorted.sort (MarkerComparator ());
329 
330  list<Marker*>::iterator i = sorted.begin ();
331 
332  list<Marker*>::iterator prev = sorted.end ();
333  list<Marker*>::iterator next = i;
334 
335  if (next != sorted.end()) {
336  ++next;
337  }
338 
339  while (i != sorted.end()) {
340 
341  if (prev != sorted.end()) {
342  double const p = sample_to_pixel ((*i)->position() - (*prev)->position());
343 
344  if ((*prev)->label_on_left()) {
345  (*i)->set_left_label_limit (p);
346  } else {
347  (*i)->set_left_label_limit (p / 2);
348  }
349 
350  }
351 
352  if (next != sorted.end()) {
353  double const p = sample_to_pixel ((*next)->position() - (*i)->position());
354 
355  if ((*next)->label_on_left()) {
356  (*i)->set_right_label_limit (p / 2);
357  } else {
358  (*i)->set_right_label_limit (p);
359  }
360 
361  ++next;
362  }
363 
364  prev = i;
365  ++i;
366  }
367 }
368 
369 void
371 {
372  ENSURE_GUI_THREAD (*this, &Editor::location_flags_changed, location, src)
373 
374  LocationMarkers *lam = find_location_markers (location);
375 
376  if (lam == 0) {
377  /* a location that isn't "marked" with markers */
378  return;
379  }
380 
381  // move cd markers to/from cd marker bar as appropriate
382  ensure_cd_marker_updated (lam, location);
383 
384  if (location->is_cd_marker()) {
385  lam->set_color_rgba (location_cd_marker_color);
386  } else if (location->is_mark()) {
387  lam->set_color_rgba (location_marker_color);
388  } else if (location->is_auto_punch()) {
389  lam->set_color_rgba (location_punch_color);
390  } else if (location->is_auto_loop()) {
391  lam->set_color_rgba (location_loop_color);
392  } else {
393  lam->set_color_rgba (location_range_color);
394  }
395 
396  if (location->is_hidden()) {
397  lam->hide();
398  } else {
399  lam->show ();
400  }
401 }
402 
404 {
405  for (LocationMarkerMap::iterator i = location_markers.begin(); i != location_markers.end(); ++i) {
406  LocationMarkers * lam = i->second;
407  Location * location = i->first;
408 
409  ensure_cd_marker_updated (lam, location);
410  }
411 }
412 
414 {
415  if (location->is_cd_marker()
416  && (ruler_cd_marker_action->get_active() && lam->start->get_parent() != cd_marker_group))
417  {
418  //cerr << "reparenting non-cd marker so it can be relocated: " << location->name() << endl;
419  if (lam->start) {
420  lam->start->reparent (*cd_marker_group);
421  }
422  if (lam->end) {
423  lam->end->reparent (*cd_marker_group);
424  }
425  }
426  else if ( (!location->is_cd_marker() || !ruler_cd_marker_action->get_active())
427  && (lam->start->get_parent() == cd_marker_group))
428  {
429  //cerr << "reparenting non-cd marker so it can be relocated: " << location->name() << endl;
430  if (location->is_mark()) {
431  if (lam->start) {
432  lam->start->reparent (*marker_group);
433  }
434  if (lam->end) {
435  lam->end->reparent (*marker_group);
436  }
437  }
438  else {
439  if (lam->start) {
440  lam->start->reparent (*range_marker_group);
441  }
442  if (lam->end) {
443  lam->end->reparent (*range_marker_group);
444  }
445  }
446  }
447 }
448 
450 {
451  delete start;
452  delete end;
453 }
454 
457 {
458  LocationMarkerMap::const_iterator i;
459 
460  for (i = location_markers.begin(); i != location_markers.end(); ++i) {
461  if ((*i).first == location) {
462  return (*i).second;
463  }
464  }
465 
466  return 0;
467 }
468 
469 Location *
470 Editor::find_location_from_marker (Marker *marker, bool& is_start) const
471 {
472  LocationMarkerMap::const_iterator i;
473 
474  for (i = location_markers.begin(); i != location_markers.end(); ++i) {
475  LocationMarkers *lm = (*i).second;
476  if (lm->start == marker) {
477  is_start = true;
478  return (*i).first;
479  } else if (lm->end == marker) {
480  is_start = false;
481  return (*i).first;
482  }
483  }
484 
485  return 0;
486 }
487 
488 void
490 {
491  /* invalidate all */
492 
493  for (LocationMarkerMap::iterator i = location_markers.begin(); i != location_markers.end(); ++i) {
494  i->second->valid = false;
495  }
496 
497  /* add new ones */
498 
499  for (Locations::LocationList::const_iterator i = locations.begin(); i != locations.end(); ++i) {
500 
501  LocationMarkerMap::iterator x;
502 
503  if ((x = location_markers.find (*i)) != location_markers.end()) {
504  x->second->valid = true;
505  continue;
506  }
507 
508  add_new_location_internal (*i);
509  }
510 
511  /* remove dead ones */
512 
513  for (LocationMarkerMap::iterator i = location_markers.begin(); i != location_markers.end(); ) {
514 
515  LocationMarkerMap::iterator tmp;
516 
517  tmp = i;
518  ++tmp;
519 
520  if (!i->second->valid) {
521 
522  remove_sorted_marker (i->second->start);
523  if (i->second->end) {
524  remove_sorted_marker (i->second->end);
525  }
526 
527  LocationMarkers* m = i->second;
528  location_markers.erase (i);
529  delete m;
530  }
531 
532  i = tmp;
533  }
534 
535  update_punch_range_view ();
536  update_loop_range_view ();
537 }
538 
539 void
541 {
543 
544  if (_session) {
545  _session->locations()->apply (*this, &Editor::refresh_location_display_internal);
546  }
547 
548  update_marker_labels ();
549 }
550 
551 void
553 {
554  start->hide ();
555  if (end) {
556  end->hide ();
557  }
558 }
559 
560 void
562 {
563  start->show ();
564  if (end) {
565  end->show ();
566  }
567 }
568 
569 void
571 {
572  start->canvas_height_set (h);
573  if (end) {
574  end->canvas_height_set (h);
575  }
576 }
577 
578 void
580 {
581  /* XXX: hack: don't change names of session start/end markers */
582 
583  if (start->type() != Marker::SessionStart) {
584  start->set_name (str);
585  }
586 
587  if (end && end->type() != Marker::SessionEnd) {
588  end->set_name (str);
589  }
590 }
591 
592 void
594  framepos_t endf)
595 {
596  start->set_position (startf);
597  if (end) {
598  end->set_position (endf);
599  }
600 }
601 
602 void
604 {
605  start->set_color_rgba (rgba);
606  if (end) {
607  end->set_color_rgba (rgba);
608  }
609 }
610 
611 void
613 {
614  start->set_show_line (s);
615  if (end) {
616  end->set_show_line (s);
617  }
618 }
619 
620 void
622 {
623  start->set_selected (s);
624  if (end) {
625  end->set_selected (s);
626  }
627 }
628 
629 void
631 {
632  start->setup_line ();
633  if (end) {
634  end->setup_line ();
635  }
636 }
637 
638 void
640 {
641  string markername;
642  int flags = (is_cd ? Location::IsCDMarker|Location::IsMark : Location::IsMark);
643 
644  if (_session) {
645  _session->locations()->next_available_name(markername, _("mark"));
646  if (!choose_new_marker_name(markername)) {
647  return;
648  }
649  Location *location = new Location (*_session, where, where, markername, (Location::Flags) flags);
650  begin_reversible_command (_("add marker"));
651 
652  XMLNode &before = _session->locations()->get_state();
653  _session->locations()->add (location, true);
654  XMLNode &after = _session->locations()->get_state();
655  _session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
656 
657  /* find the marker we just added */
658 
659  LocationMarkers *lam = find_location_markers (location);
660  if (lam) {
661  /* make it the selected marker */
662  selection->set (lam->start);
663  }
664 
665  commit_reversible_command ();
666  }
667 }
668 
669 void
671 {
672  if (!_session) {
673  return;
674  }
675 
676  /* Make this marker 1/8th of the visible area of the session so that
677  it's reasonably easy to manipulate after creation.
678  */
679 
680  framepos_t const end = where + current_page_samples() / 8;
681 
682  set_loop_range (where, end, _("set loop range"));
683 }
684 
685 void
687 {
688  if (!_session) {
689  return;
690  }
691 
692  /* Make this marker 1/8th of the visible area of the session so that
693  it's reasonably easy to manipulate after creation.
694  */
695 
696  framepos_t const end = where + current_page_samples() / 8;
697 
698  set_punch_range (where, end, _("set punch range"));
699 }
700 
701 void
703 {
704  if (!_session) {
705  return;
706  }
707 
708  /* Make this marker 1/8th of the visible area of the session so that
709  it's reasonably easy to manipulate after creation.
710  */
711 
712  framepos_t const end = where + current_page_samples() / 8;
713 
714  string name;
715  _session->locations()->next_available_name (name, _("range"));
716  Location* loc = new Location (*_session, where, end, name, Location::IsRangeMarker);
717 
718  begin_reversible_command (_("new range marker"));
719  XMLNode& before = _session->locations()->get_state ();
720  _session->locations()->add (loc, true);
721  XMLNode& after = _session->locations()->get_state ();
722  _session->add_command (new MementoCommand<Locations> (*_session->locations(), &before, &after));
723  commit_reversible_command ();
724 }
725 
726 void
727 Editor::remove_marker (ArdourCanvas::Item& item, GdkEvent*)
728 {
729  Marker* marker;
730  bool is_start;
731 
732  if ((marker = static_cast<Marker*> (item.get_data ("marker"))) == 0) {
733  fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg;
734  abort(); /*NOTREACHED*/
735  }
736 
737  if (entered_marker == marker) {
738  entered_marker = NULL;
739  }
740 
741  Location* loc = find_location_from_marker (marker, is_start);
742 
743  if (_session && loc) {
744  Glib::signal_idle().connect (sigc::bind (sigc::mem_fun(*this, &Editor::really_remove_marker), loc));
745  }
746 }
747 
748 gint
750 {
751  begin_reversible_command (_("remove marker"));
752  XMLNode &before = _session->locations()->get_state();
753  _session->locations()->remove (loc);
754  XMLNode &after = _session->locations()->get_state();
755  _session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
756  commit_reversible_command ();
757  return FALSE;
758 }
759 
760 void
762 {
763  ENSURE_GUI_THREAD (*this, &Editor::location_gone, location)
764 
765  LocationMarkerMap::iterator i;
766 
767  if (location == transport_loop_location()) {
768  update_loop_range_view ();
769  }
770 
771  if (location == transport_punch_location()) {
772  update_punch_range_view ();
773  }
774 
775  for (i = location_markers.begin(); i != location_markers.end(); ++i) {
776  if (i->first == location) {
777 
778  remove_sorted_marker (i->second->start);
779  if (i->second->end) {
780  remove_sorted_marker (i->second->end);
781  }
782 
783  LocationMarkers* m = i->second;
784  location_markers.erase (i);
785  delete m;
786  break;
787  }
788  }
789 }
790 
791 void
792 Editor::tempo_or_meter_marker_context_menu (GdkEventButton* ev, ArdourCanvas::Item* item)
793 {
794  marker_menu_item = item;
795 
796  MeterMarker* mm;
797  TempoMarker* tm;
798  dynamic_cast_marker_object (marker_menu_item->get_data ("marker"), &mm, &tm);
799 
800  bool can_remove = false;
801 
802  if (mm) {
803  can_remove = mm->meter().movable ();
804  } else if (tm) {
805  can_remove = tm->tempo().movable ();
806  } else {
807  return;
808  }
809 
810  delete tempo_or_meter_marker_menu;
811  build_tempo_or_meter_marker_menu (can_remove);
812  tempo_or_meter_marker_menu->popup (1, ev->time);
813 }
814 
815 void
816 Editor::marker_context_menu (GdkEventButton* ev, ArdourCanvas::Item* item)
817 {
818  Marker * marker;
819  if ((marker = reinterpret_cast<Marker *> (item->get_data("marker"))) == 0) {
820  fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg;
821  abort(); /*NOTREACHED*/
822  }
823 
824  bool is_start;
825  Location * loc = find_location_from_marker (marker, is_start);
826 
827  if (loc == transport_loop_location() || loc == transport_punch_location() || loc->is_session_range ()) {
828 
829  if (transport_marker_menu == 0) {
830  build_range_marker_menu (loc == transport_loop_location() || loc == transport_punch_location(), loc->is_session_range());
831  }
832 
833  marker_menu_item = item;
834  transport_marker_menu->popup (1, ev->time);
835 
836  } else if (loc->is_mark()) {
837 
838  delete marker_menu;
839  build_marker_menu (loc);
840 
841  // GTK2FIX use action group sensitivity
842 #ifdef GTK2FIX
843  if (children.size() >= 3) {
844  MenuItem * loopitem = &children[2];
845  if (loopitem) {
846  if (loc->is_mark()) {
847  loopitem->set_sensitive(false);
848  }
849  else {
850  loopitem->set_sensitive(true);
851  }
852  }
853  }
854 #endif
855  marker_menu_item = item;
856  marker_menu->popup (1, ev->time);
857 
858  } else if (loc->is_range_marker()) {
859  if (range_marker_menu == 0) {
860  build_range_marker_menu (false, false);
861  }
862  marker_menu_item = item;
863  range_marker_menu->popup (1, ev->time);
864  }
865 }
866 
867 void
868 Editor::new_transport_marker_context_menu (GdkEventButton* ev, ArdourCanvas::Item*)
869 {
870  if (new_transport_marker_menu == 0) {
871  build_new_transport_marker_menu ();
872  }
873 
874  new_transport_marker_menu->popup (1, ev->time);
875 
876 }
877 
878 void
880 {
881  using namespace Menu_Helpers;
882 
883  marker_menu = new Menu;
884  MenuList& items = marker_menu->items();
885  marker_menu->set_name ("ArdourContextMenu");
886 
887  items.push_back (MenuElem (_("Locate to Here"), sigc::mem_fun(*this, &Editor::marker_menu_set_playhead)));
888  items.push_back (MenuElem (_("Play from Here"), sigc::mem_fun(*this, &Editor::marker_menu_play_from)));
889  items.push_back (MenuElem (_("Move Mark to Playhead"), sigc::mem_fun(*this, &Editor::marker_menu_set_from_playhead)));
890 
891  items.push_back (SeparatorElem());
892 
893  items.push_back (MenuElem (_("Create Range to Next Marker"), sigc::mem_fun(*this, &Editor::marker_menu_range_to_next)));
894 
895  items.push_back (MenuElem (_("Hide"), sigc::mem_fun(*this, &Editor::marker_menu_hide)));
896  items.push_back (MenuElem (_("Rename..."), sigc::mem_fun(*this, &Editor::marker_menu_rename)));
897 
898  items.push_back (CheckMenuElem (_("Lock")));
899  Gtk::CheckMenuItem* lock_item = static_cast<Gtk::CheckMenuItem*> (&items.back());
900  if (loc->locked ()) {
901  lock_item->set_active ();
902  }
903  lock_item->signal_activate().connect (sigc::mem_fun (*this, &Editor::toggle_marker_menu_lock));
904 
905  items.push_back (CheckMenuElem (_("Glue to Bars and Beats")));
906  Gtk::CheckMenuItem* glue_item = static_cast<Gtk::CheckMenuItem*> (&items.back());
907  if (loc->position_lock_style() == MusicTime) {
908  glue_item->set_active ();
909  }
910  glue_item->signal_activate().connect (sigc::mem_fun (*this, &Editor::toggle_marker_menu_glue));
911 
912  items.push_back (SeparatorElem());
913 
914  items.push_back (MenuElem (_("Remove"), sigc::mem_fun(*this, &Editor::marker_menu_remove)));
915 }
916 
917 void
918 Editor::build_range_marker_menu (bool loop_or_punch, bool session)
919 {
920  using namespace Menu_Helpers;
921 
922  bool const loop_or_punch_or_session = loop_or_punch | session;
923 
924  Menu *markerMenu = new Menu;
925  if (loop_or_punch_or_session) {
926  transport_marker_menu = markerMenu;
927  } else {
928  range_marker_menu = markerMenu;
929  }
930  MenuList& items = markerMenu->items();
931  markerMenu->set_name ("ArdourContextMenu");
932 
933  items.push_back (MenuElem (_("Play Range"), sigc::mem_fun(*this, &Editor::marker_menu_play_range)));
934  items.push_back (MenuElem (_("Locate to Marker"), sigc::mem_fun(*this, &Editor::marker_menu_set_playhead)));
935  items.push_back (MenuElem (_("Play from Marker"), sigc::mem_fun(*this, &Editor::marker_menu_play_from)));
936  items.push_back (MenuElem (_("Loop Range"), sigc::mem_fun(*this, &Editor::marker_menu_loop_range)));
937 
938  items.push_back (MenuElem (_("Set Marker from Playhead"), sigc::mem_fun(*this, &Editor::marker_menu_set_from_playhead)));
939  if (!Profile->get_sae()) {
940  items.push_back (MenuElem (_("Set Range from Selection"), sigc::bind (sigc::mem_fun(*this, &Editor::marker_menu_set_from_selection), false)));
941  }
942 
943  items.push_back (MenuElem (_("Zoom to Range"), sigc::mem_fun (*this, &Editor::marker_menu_zoom_to_range)));
944 
945  items.push_back (SeparatorElem());
946  items.push_back (MenuElem (_("Export Range..."), sigc::mem_fun(*this, &Editor::export_range)));
947  items.push_back (SeparatorElem());
948 
949  if (!loop_or_punch_or_session) {
950  items.push_back (MenuElem (_("Hide Range"), sigc::mem_fun(*this, &Editor::marker_menu_hide)));
951  items.push_back (MenuElem (_("Rename Range..."), sigc::mem_fun(*this, &Editor::marker_menu_rename)));
952  }
953 
954  if (!session) {
955  items.push_back (MenuElem (_("Remove Range"), sigc::mem_fun(*this, &Editor::marker_menu_remove)));
956  }
957 
958  if (!loop_or_punch_or_session || !session) {
959  items.push_back (SeparatorElem());
960  }
961 
962  items.push_back (MenuElem (_("Separate Regions in Range"), sigc::mem_fun(*this, &Editor::marker_menu_separate_regions_using_location)));
963  items.push_back (MenuElem (_("Select All in Range"), sigc::mem_fun(*this, &Editor::marker_menu_select_all_selectables_using_range)));
964  if (!Profile->get_sae()) {
965  items.push_back (MenuElem (_("Select Range"), sigc::mem_fun(*this, &Editor::marker_menu_select_using_range)));
966  }
967 }
968 
969 void
971 {
972  using namespace Menu_Helpers;
973 
974  tempo_or_meter_marker_menu = new Menu;
975  MenuList& items = tempo_or_meter_marker_menu->items();
976  tempo_or_meter_marker_menu->set_name ("ArdourContextMenu");
977 
978  items.push_back (MenuElem (_("Edit..."), sigc::mem_fun(*this, &Editor::marker_menu_edit)));
979  items.push_back (MenuElem (_("Remove"), sigc::mem_fun(*this, &Editor::marker_menu_remove)));
980 
981  items.back().set_sensitive (can_remove);
982 }
983 
984 void
986 {
987  using namespace Menu_Helpers;
988 
989  new_transport_marker_menu = new Menu;
990  MenuList& items = new_transport_marker_menu->items();
991  new_transport_marker_menu->set_name ("ArdourContextMenu");
992 
993  items.push_back (MenuElem (_("Set Loop Range"), sigc::mem_fun(*this, &Editor::new_transport_marker_menu_set_loop)));
994  items.push_back (MenuElem (_("Set Punch Range"), sigc::mem_fun(*this, &Editor::new_transport_marker_menu_set_punch)));
995 
996  new_transport_marker_menu->signal_unmap().connect ( sigc::mem_fun(*this, &Editor::new_transport_marker_menu_popdown));
997 }
998 
999 void
1001 {
1002  Marker* marker;
1003 
1004  if ((marker = reinterpret_cast<Marker *> (marker_menu_item->get_data ("marker"))) == 0) {
1005  fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg;
1006  abort(); /*NOTREACHED*/
1007  }
1008 
1009  Location* l;
1010  bool is_start;
1011 
1012  if ((l = find_location_from_marker (marker, is_start)) != 0) {
1013  l->set_hidden (true, this);
1014  }
1015 }
1016 
1017 void
1019 {
1020  Marker* marker;
1021 
1022  if ((marker = reinterpret_cast<Marker *> (marker_menu_item->get_data ("marker"))) == 0) {
1023  fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg;
1024  abort(); /*NOTREACHED*/
1025  }
1026 
1027  Location* l;
1028  bool is_start;
1029 
1030  if (((l = find_location_from_marker (marker, is_start)) != 0) && (l->end() > l->start())) {
1031  set_selection_from_range (*l);
1032  }
1033 }
1034 
1035 void
1037 {
1038  Marker* marker;
1039 
1040  if ((marker = reinterpret_cast<Marker *> (marker_menu_item->get_data ("marker"))) == 0) {
1041  fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg;
1042  abort(); /*NOTREACHED*/
1043  }
1044 
1045  Location* l;
1046  bool is_start;
1047 
1048  if (((l = find_location_from_marker (marker, is_start)) != 0) && (l->end() > l->start())) {
1049  select_all_within (l->start(), l->end() - 1, 0, DBL_MAX, track_views, Selection::Set, false);
1050  }
1051 
1052 }
1053 
1054 void
1056 {
1057  Marker* marker;
1058 
1059  if ((marker = reinterpret_cast<Marker *> (marker_menu_item->get_data ("marker"))) == 0) {
1060  fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg;
1061  abort(); /*NOTREACHED*/
1062  }
1063 
1064  Location* l;
1065  bool is_start;
1066 
1067  if (((l = find_location_from_marker (marker, is_start)) != 0) && (l->end() > l->start())) {
1068  separate_regions_using_location (*l);
1069  }
1070 
1071 }
1072 
1073 void
1075 {
1076  Marker* marker;
1077 
1078  if ((marker = reinterpret_cast<Marker *> (marker_menu_item->get_data ("marker"))) == 0) {
1079  fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg;
1080  abort(); /*NOTREACHED*/
1081  }
1082 
1083  Location* l;
1084  bool is_start;
1085 
1086  if ((l = find_location_from_marker (marker, is_start)) != 0) {
1087 
1088  if (l->is_mark()) {
1089  _session->request_locate (l->start(), true);
1090  }
1091  else {
1092  //_session->request_bounded_roll (l->start(), l->end());
1093 
1094  if (is_start) {
1095  _session->request_locate (l->start(), true);
1096  } else {
1097  _session->request_locate (l->end(), true);
1098  }
1099  }
1100  }
1101 }
1102 
1103 void
1105 {
1106  Marker* marker;
1107 
1108  if ((marker = reinterpret_cast<Marker *> (marker_menu_item->get_data ("marker"))) == 0) {
1109  fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg;
1110  abort(); /*NOTREACHED*/
1111  }
1112 
1113  Location* l;
1114  bool is_start;
1115 
1116  if ((l = find_location_from_marker (marker, is_start)) != 0) {
1117 
1118  if (l->is_mark()) {
1119  _session->request_locate (l->start(), false);
1120  }
1121  else {
1122  if (is_start) {
1123  _session->request_locate (l->start(), false);
1124  } else {
1125  _session->request_locate (l->end(), false);
1126  }
1127  }
1128  }
1129 }
1130 
1131 void
1133 {
1134  Marker* marker;
1135  if (!_session) {
1136  return;
1137  }
1138 
1139  if ((marker = reinterpret_cast<Marker *> (marker_menu_item->get_data ("marker"))) == 0) {
1140  fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg;
1141  abort(); /*NOTREACHED*/
1142  }
1143 
1144  Location* l;
1145  bool is_start;
1146 
1147  if ((l = find_location_from_marker (marker, is_start)) == 0) {
1148  return;
1149  }
1150 
1151  framepos_t start;
1152  framepos_t end;
1153  _session->locations()->marks_either_side (marker->position(), start, end);
1154 
1155  if (end != max_framepos) {
1156  string range_name = l->name();
1157  range_name += "-range";
1158 
1159  Location* newrange = new Location (*_session, marker->position(), end, range_name, Location::IsRangeMarker);
1160  _session->locations()->add (newrange);
1161  }
1162 }
1163 
1164 void
1166 {
1167  Marker* marker;
1168 
1169  if ((marker = reinterpret_cast<Marker *> (marker_menu_item->get_data ("marker"))) == 0) {
1170  fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg;
1171  abort(); /*NOTREACHED*/
1172  }
1173 
1174  Location* l;
1175  bool is_start;
1176 
1177  if ((l = find_location_from_marker (marker, is_start)) != 0) {
1178 
1179  if (l->is_mark()) {
1180  l->set_start (_session->audible_frame ());
1181  }
1182  else {
1183  if (is_start) {
1184  l->set_start (_session->audible_frame ());
1185  } else {
1186  l->set_end (_session->audible_frame ());
1187  }
1188  }
1189  }
1190 }
1191 
1192 void
1194 {
1195  Marker* marker;
1196 
1197  if ((marker = reinterpret_cast<Marker *> (marker_menu_item->get_data ("marker"))) == 0) {
1198  fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg;
1199  abort(); /*NOTREACHED*/
1200  }
1201 
1202  Location* l;
1203  bool is_start;
1204 
1205  if ((l = find_location_from_marker (marker, is_start)) != 0) {
1206 
1207  if (l->is_mark()) {
1208 
1209  // nothing for now
1210 
1211  } else {
1212 
1213  if (!selection->time.empty()) {
1214  l->set (selection->time.start(), selection->time.end_frame());
1215  } else if (!selection->regions.empty()) {
1216  l->set (selection->regions.start(), selection->regions.end_frame());
1217  }
1218  }
1219  }
1220 }
1221 
1222 
1223 void
1225 {
1226  Marker* marker;
1227 
1228  if ((marker = reinterpret_cast<Marker *> (marker_menu_item->get_data ("marker"))) == 0) {
1229  fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg;
1230  abort(); /*NOTREACHED*/
1231  }
1232 
1233  Location* l;
1234  bool is_start;
1235 
1236  if ((l = find_location_from_marker (marker, is_start)) != 0) {
1237 
1238  if (l->is_mark()) {
1239  _session->request_locate (l->start(), true);
1240  }
1241  else {
1242  _session->request_bounded_roll (l->start(), l->end());
1243 
1244  }
1245  }
1246 }
1247 
1248 void
1250 {
1251  Marker* marker;
1252 
1253  if ((marker = reinterpret_cast<Marker *> (marker_menu_item->get_data ("marker"))) == 0) {
1254  fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg;
1255  abort(); /*NOTREACHED*/
1256  }
1257 
1258  Location* l;
1259  bool is_start;
1260 
1261  if ((l = find_location_from_marker (marker, is_start)) != 0) {
1262  Location* l2;
1263  if ((l2 = transport_loop_location()) != 0) {
1264  l2->set (l->start(), l->end());
1265 
1266  // enable looping, reposition and start rolling
1267  _session->request_locate (l2->start(), true);
1268  _session->request_play_loop(true);
1269  }
1270  }
1271 }
1272 
1274 void
1276 {
1277  Marker* marker = reinterpret_cast<Marker *> (marker_menu_item->get_data ("marker"));
1278  assert (marker);
1279 
1280  bool is_start;
1281  Location* l = find_location_from_marker (marker, is_start);
1282  if (l == 0) {
1283  return;
1284  }
1285 
1286  framecnt_t const extra = l->length() * 0.05;
1287  framepos_t a = l->start ();
1288  if (a >= extra) {
1289  a -= extra;
1290  }
1291 
1292  framepos_t b = l->end ();
1293  if (b < (max_framepos - extra)) {
1294  b += extra;
1295  }
1296 
1297  temporal_zoom_by_frame (a, b);
1298 }
1299 
1300 void
1302 {
1303  Marker* marker = reinterpret_cast<Marker*> (p);
1304  if (!marker) {
1305  fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg;
1306  abort(); /*NOTREACHED*/
1307  }
1308 
1309  *m = dynamic_cast<MeterMarker*> (marker);
1310  *t = dynamic_cast<TempoMarker*> (marker);
1311 }
1312 
1313 void
1315 {
1316  MeterMarker* mm;
1317  TempoMarker* tm;
1318  dynamic_cast_marker_object (marker_menu_item->get_data ("marker"), &mm, &tm);
1319 
1320  if (mm) {
1321  edit_meter_section (&mm->meter());
1322  } else if (tm) {
1323  edit_tempo_section (&tm->tempo());
1324  }
1325 }
1326 
1327 void
1329 {
1330  MeterMarker* mm;
1331  TempoMarker* tm;
1332  dynamic_cast_marker_object (marker_menu_item->get_data ("marker"), &mm, &tm);
1333 
1334  if (mm) {
1335  remove_meter_marker (marker_menu_item);
1336  } else if (tm) {
1337  remove_tempo_marker (marker_menu_item);
1338  } else {
1339  remove_marker (*marker_menu_item, (GdkEvent*) 0);
1340  }
1341 }
1342 
1343 void
1345 {
1346  Marker* marker;
1347 
1348  if ((marker = reinterpret_cast<Marker *> (marker_menu_item->get_data ("marker"))) == 0) {
1349  fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg;
1350  abort(); /*NOTREACHED*/
1351  }
1352 
1353  Location* loc;
1354  bool ignored;
1355 
1356  loc = find_location_from_marker (marker, ignored);
1357 
1358  if (!loc) {
1359  return;
1360  }
1361 
1362  if (loc->locked()) {
1363  loc->unlock ();
1364  } else {
1365  loc->lock ();
1366  }
1367 }
1368 
1369 void
1371 {
1372  Marker* marker;
1373 
1374  if ((marker = reinterpret_cast<Marker *> (marker_menu_item->get_data ("marker"))) == 0) {
1375  fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg;
1376  abort(); /*NOTREACHED*/
1377  }
1378 
1379 
1380  rename_marker (marker);
1381 }
1382 
1383 void
1385 {
1386  Location* loc;
1387  bool is_start;
1388 
1389  loc = find_location_from_marker (marker, is_start);
1390 
1391  if (!loc)
1392  return;
1393 
1394  if (loc == transport_loop_location() || loc == transport_punch_location() || loc->is_session_range())
1395  return;
1396 
1397  ArdourPrompter dialog (true);
1398  string txt;
1399 
1400  dialog.set_prompt (_("New Name:"));
1401 
1402  if (loc->is_mark()) {
1403  dialog.set_title (_("Rename Mark"));
1404  } else {
1405  dialog.set_title (_("Rename Range"));
1406  }
1407 
1408  dialog.set_name ("MarkRenameWindow");
1409  dialog.set_size_request (250, -1);
1410  dialog.set_position (Gtk::WIN_POS_MOUSE);
1411 
1412  dialog.add_button (_("Rename"), RESPONSE_ACCEPT);
1413  dialog.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
1414  dialog.set_initial_text (loc->name());
1415 
1416  dialog.show ();
1417 
1418  switch (dialog.run ()) {
1419  case RESPONSE_ACCEPT:
1420  break;
1421  default:
1422  return;
1423  }
1424 
1425  begin_reversible_command ( _("rename marker") );
1426  XMLNode &before = _session->locations()->get_state();
1427 
1428  dialog.get_result(txt);
1429  loc->set_name (txt);
1430  _session->set_dirty ();
1431 
1432  XMLNode &after = _session->locations()->get_state();
1433  _session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
1434  commit_reversible_command ();
1435 }
1436 
1437 void
1439 {
1440  // hide rects
1441  transport_bar_drag_rect->hide();
1442 
1443  _drags->abort ();
1444 }
1445 
1446 void
1448 {
1449  set_loop_range (temp_location->start(), temp_location->end(), _("set loop range"));
1450 }
1451 
1452 void
1454 {
1455  set_punch_range (temp_location->start(), temp_location->end(), _("set punch range"));
1456 }
1457 
1458 void
1460 {
1461  if (_session == 0) {
1462  return;
1463  }
1464 
1465  Location* tll;
1466 
1467  if (_session->get_play_loop() && ((tll = transport_loop_location()) != 0)) {
1468 
1469  double x1 = sample_to_pixel (tll->start());
1470  double x2 = sample_to_pixel (tll->end());
1471 
1472  transport_loop_range_rect->set_x0 (x1);
1473  transport_loop_range_rect->set_x1 (x2);
1474 
1475  transport_loop_range_rect->show();
1476 
1477  } else {
1478  transport_loop_range_rect->hide();
1479  }
1480 }
1481 
1482 void
1484 {
1485  if (_session == 0) {
1486  return;
1487  }
1488 
1489  Location* tpl;
1490 
1491  if ((_session->config.get_punch_in() || _session->config.get_punch_out()) && ((tpl = transport_punch_location()) != 0)) {
1492 
1493  double pixel_start;
1494  double pixel_end;
1495 
1496  if (_session->config.get_punch_in()) {
1497  pixel_start = sample_to_pixel (tpl->start());
1498  } else {
1499  pixel_start = 0;
1500  }
1501  if (_session->config.get_punch_out()) {
1502  pixel_end = sample_to_pixel (tpl->end());
1503  } else {
1504  pixel_end = sample_to_pixel (max_framepos);
1505  }
1506 
1507  transport_punch_range_rect->set_x0 (pixel_start);
1508  transport_punch_range_rect->set_x1 (pixel_end);
1509  transport_punch_range_rect->show();
1510 
1511  } else {
1512 
1513  transport_punch_range_rect->hide();
1514  }
1515 }
1516 
1517 void
1519 {
1520  if (_session && _session->deletion_in_progress()) {
1521  return;
1522  }
1523 
1524  for (LocationMarkerMap::iterator i = location_markers.begin(); i != location_markers.end(); ++i) {
1525  i->second->set_selected (false);
1526  }
1527 
1528  for (MarkerSelection::iterator x = selection->markers.begin(); x != selection->markers.end(); ++x) {
1529  (*x)->set_selected (true);
1530  }
1531 }
1532 
1534  bool operator() (Location* a, Location* b) {
1535  return a->start() < b->start();
1536  }
1537 };
1538 
1539 void
1541 {
1542  if (!_session) {
1543  return;
1544  }
1545  const Locations::LocationList& l (_session->locations()->list());
1546  Locations::LocationList ordered;
1547  ordered = l;
1548 
1550  ordered.sort (cmp);
1551 
1552  for (Locations::LocationList::iterator i = ordered.begin(); n >= 0 && i != ordered.end(); ++i) {
1553  if ((*i)->is_mark() && !(*i)->is_hidden() && !(*i)->is_session_range()) {
1554  if (n == 0) {
1555  _session->request_locate ((*i)->start(), _session->transport_rolling());
1556  break;
1557  }
1558  --n;
1559  }
1560  }
1561 }
1562 
1563 void
1565 {
1566  Marker* marker;
1567 
1568  if ((marker = reinterpret_cast<Marker *> (marker_menu_item->get_data ("marker"))) == 0) {
1569  fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg;
1570  abort(); /*NOTREACHED*/
1571  }
1572 
1573  Location* loc;
1574  bool ignored;
1575 
1576  loc = find_location_from_marker (marker, ignored);
1577 
1578  if (!loc) {
1579  return;
1580  }
1581 
1582  if (loc->position_lock_style() == MusicTime) {
1584  } else {
1586  }
1587 
1588 }
1589 
1590 void
1592 {
1593  _show_marker_lines = !_show_marker_lines;
1594 
1595  for (LocationMarkerMap::iterator i = location_markers.begin(); i != location_markers.end(); ++i) {
1596  i->second->set_show_lines (_show_marker_lines);
1597  }
1598 }
1599 
1600 void
1602 {
1603  for (std::map<ArdourCanvas::Container *, std::list<Marker *> >::iterator i = _sorted_marker_lists.begin(); i != _sorted_marker_lists.end(); ++i) {
1604  i->second.remove (m);
1605  }
1606 }
1607 
1608 Marker *
1609 Editor::find_marker_from_location_id (PBD::ID const & id, bool is_start) const
1610 {
1611  for (LocationMarkerMap::const_iterator i = location_markers.begin(); i != location_markers.end(); ++i) {
1612  if (i->first->id() == id) {
1613  return is_start ? i->second->start : i->second->end;
1614  }
1615  }
1616 
1617  return 0;
1618 }
void marker_menu_separate_regions_using_location()
session end
Definition: marker.h:49
void marker_menu_range_to_next()
LIBPBD_API Transmitter fatal
void canvas_height_set(double)
void update_loop_range_view()
#define Marker
Definition: au_pluginui.mm:2
void marker_menu_edit()
void marker_context_menu(GdkEventButton *, ArdourCanvas::Item *)
void remove_sorted_marker(Marker *)
bool get_sae() const
Definition: profile.h:48
void marker_menu_select_using_range()
void set_left_label_limit(double)
Definition: marker.cc:491
void add_new_location(ARDOUR::Location *)
std::list< Location * > LocationList
Definition: location.h:167
void toggle_marker_menu_glue()
framepos_t position() const
Definition: marker.h:79
void tempo_or_meter_marker_context_menu(GdkEventButton *, ArdourCanvas::Item *)
void set_name(const std::string &str)
Definition: location.cc:167
Definition: ardour_ui.h:130
Definition: marker.h:41
void mouse_add_new_marker(framepos_t where, bool is_cd=false)
framepos_t end() const
Definition: location.h:72
Definition: Beats.hpp:239
ARDOUR::TempoSection & tempo() const
Definition: marker.h:142
void toggle_marker_lines()
bool movable() const
Definition: tempo.h:103
void update_cd_marker_display()
std::ostream & endmsg(std::ostream &ostr)
Definition: transmitter.h:71
bool is_cd_marker() const
Definition: location.h:96
session start
Definition: marker.h:48
LIBARDOUR_API PBD::PropertyDescriptor< framepos_t > start
Definition: region.cc:63
bool is_hidden() const
Definition: location.h:95
#define ENSURE_GUI_THREAD(obj, method,...)
Definition: gui_thread.h:34
#define invalidator(x)
Definition: gui_thread.h:40
bool is_session_range() const
Definition: location.h:97
void set_initial_text(std::string txt)
Definition: prompter.h:50
ArdourCanvas::Container * add_new_location_internal(ARDOUR::Location *)
void new_transport_marker_context_menu(GdkEventButton *, ArdourCanvas::Item *)
Definition: id.h:32
void reparent(ArdourCanvas::Container &parent)
Definition: marker.cc:317
void new_transport_marker_menu_set_punch()
void set_color_rgba(uint32_t)
#define _(Text)
Definition: i18n.h:11
PositionLockStyle position_lock_style() const
Definition: location.h:142
void location_changed(ARDOUR::Location *)
void marker_selection_changed()
void location_gone(ARDOUR::Location *)
void mouse_add_new_punch(framepos_t)
int64_t framecnt_t
Definition: types.h:76
void marker_menu_set_playhead()
void marker_menu_rename()
int set(framepos_t start, framepos_t end, bool allow_bbt_recompute=true)
Definition: location.cc:321
void clear_marker_display()
void dynamic_cast_marker_object(void *, MeterMarker **, TempoMarker **) const
void set_prompt(std::string prompt)
Definition: prompter.h:46
void marker_menu_select_all_selectables_using_range()
bool is_auto_punch() const
Definition: location.h:92
void set_right_label_limit(double)
Definition: marker.cc:506
void mouse_add_new_range(framepos_t)
PBD::Signal0< void > FlagsChanged
Definition: location.h:130
void new_transport_marker_menu_set_loop()
Definition: amp.h:29
bool locked() const
Definition: location.h:67
void marker_menu_loop_range()
bool label_on_left() const
Definition: marker.cc:390
ARDOUR::MeterSection & meter() const
Definition: marker.h:154
#define gui_context()
Definition: gui_thread.h:36
void build_range_marker_menu(bool, bool)
void marker_menu_play_from()
void update_marker_labels()
Marker * find_marker_from_location_id(PBD::ID const &, bool) const
gint really_remove_marker(ARDOUR::Location *loc)
void marker_menu_set_from_playhead()
int64_t framepos_t
Definition: types.h:66
void update_punch_range_view()
void ensure_cd_marker_updated(LocationMarkers *lam, ARDOUR::Location *location)
LIBARDOUR_API RuntimeProfile * Profile
Definition: globals.cc:120
void get_result(std::string &str, bool strip=true)
Definition: prompter.cc:104
void marker_menu_zoom_to_range()
bool is_mark() const
Definition: location.h:94
void set_name(const std::string &)
int set_start(framepos_t s, bool force=false, bool allow_bbt_recompute=true)
Definition: location.cc:181
LocationMarkers * find_location_markers(ARDOUR::Location *) const
void set_position(framepos_t start, framepos_t end=0)
void rename_marker(Marker *marker)
const char * name
ArdourCanvas::Container * get_parent()
Definition: marker.h:81
const std::string & name() const
Definition: location.h:81
Definition: xml++.h:95
ARDOUR::Location * find_location_from_marker(Marker *, bool &is_start) const
Definition: debug.h:30
framecnt_t length() const
Definition: location.h:73
void goto_nth_marker(int nth)
framepos_t start() const
Definition: location.h:71
static const framepos_t max_framepos
Definition: types.h:78
void refresh_location_display_internal(const ARDOUR::Locations::LocationList &)
bool is_range_marker() const
Definition: location.h:98
static PBD::Signal1< void, Location * > name_changed
Definition: location.h:112
void remove_marker(ArdourCanvas::Item &, GdkEvent *)
void refresh_location_display()
void toggle_marker_menu_lock()
void location_flags_changed(ARDOUR::Location *)
bool is_auto_loop() const
Definition: location.h:93
void export_range()
void marker_menu_hide()
void marker_menu_set_from_selection(bool force_regions)
void check_marker_label(Marker *)
void set_hidden(bool yn, void *src)
Definition: location.cc:441
void build_tempo_or_meter_marker_menu(bool)
void mouse_add_new_loop(framepos_t)
int set_end(framepos_t e, bool force=false, bool allow_bbt_recompute=true)
Definition: location.cc:258
void marker_menu_remove()
void build_new_transport_marker_menu()
void set_position_lock_style(PositionLockStyle ps)
Definition: location.cc:700
void marker_menu_play_range()
void new_transport_marker_menu_popdown()
void build_marker_menu(ARDOUR::Location *)
LIBARDOUR_API PBD::PropertyDescriptor< bool > color
Definition: route_group.cc:50