2 Copyright (C) 2000 Paul Davis
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.
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.
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.
20 #include <sigc++/retype.h>
24 #include <libgnomecanvas/libgnomecanvas.h>
25 #include <gtkmm2ext/gtk_ui.h>
26 #include <gtkmm2ext/window_title.h>
28 #include <ardour/location.h>
29 #include <ardour/profile.h>
30 #include <pbd/memento_command.h>
34 #include "selection.h"
36 #include "gui_thread.h"
37 #include "simplerect.h"
45 using namespace ARDOUR
;
48 using namespace Gtkmm2ext
;
51 Editor::clear_marker_display ()
53 for (LocationMarkerMap::iterator i
= location_markers
.begin(); i
!= location_markers
.end(); ++i
) {
57 location_markers
.clear ();
61 Editor::add_new_location (Location
*location
)
63 ENSURE_GUI_THREAD (bind (mem_fun(*this, &Editor::add_new_location
), location
));
65 LocationMarkers
*lam
= new LocationMarkers
;
68 if (location
->is_cd_marker()) {
69 color
= location_cd_marker_color
;
70 } else if (location
->is_mark()) {
71 color
= location_marker_color
;
72 } else if (location
->is_auto_loop()) {
73 color
= location_loop_color
;
74 } else if (location
->is_auto_punch()) {
75 color
= location_punch_color
;
77 color
= location_range_color
;
80 if (location
->is_mark()) {
82 if (location
->is_cd_marker() && ruler_cd_marker_action
->get_active()) {
83 lam
->start
= new Marker (*this, *cd_marker_group
, color
, location
->name(), Marker::Mark
, location
->start());
86 lam
->start
= new Marker (*this, *marker_group
, color
, location
->name(), Marker::Mark
, location
->start());
90 } else if (location
->is_auto_loop()) {
92 lam
->start
= new Marker (*this, *transport_marker_group
, color
,
93 location
->name(), Marker::LoopStart
, location
->start());
94 lam
->end
= new Marker (*this, *transport_marker_group
, color
,
95 location
->name(), Marker::LoopEnd
, location
->end());
97 } else if (location
->is_auto_punch()) {
99 lam
->start
= new Marker (*this, *transport_marker_group
, color
,
100 location
->name(), Marker::PunchIn
, location
->start());
101 lam
->end
= new Marker (*this, *transport_marker_group
, color
,
102 location
->name(), Marker::PunchOut
, location
->end());
106 if (location
->is_cd_marker() && ruler_cd_marker_action
->get_active()) {
107 lam
->start
= new Marker (*this, *cd_marker_group
, color
,
108 location
->name(), Marker::Start
, location
->start());
109 lam
->end
= new Marker (*this, *cd_marker_group
, color
,
110 location
->name(), Marker::End
, location
->end());
114 lam
->start
= new Marker (*this, *range_marker_group
, color
,
115 location
->name(), Marker::Start
, location
->start());
116 lam
->end
= new Marker (*this, *range_marker_group
, color
,
117 location
->name(), Marker::End
, location
->end());
121 if (location
->is_hidden ()) {
127 location
->start_changed
.connect (mem_fun(*this, &Editor::location_changed
));
128 location
->end_changed
.connect (mem_fun(*this, &Editor::location_changed
));
129 location
->changed
.connect (mem_fun(*this, &Editor::location_changed
));
130 location
->name_changed
.connect (mem_fun(*this, &Editor::location_changed
));
131 location
->FlagsChanged
.connect (mem_fun(*this, &Editor::location_flags_changed
));
133 pair
<Location
*,LocationMarkers
*> newpair
;
135 newpair
.first
= location
;
136 newpair
.second
= lam
;
138 location_markers
.insert (newpair
);
140 if (select_new_marker
&& location
->is_mark()) {
141 selection
->set (lam
->start
);
142 select_new_marker
= false;
147 Editor::location_changed (Location
*location
)
149 ENSURE_GUI_THREAD (bind (mem_fun(*this, &Editor::location_changed
), location
));
151 LocationMarkers
*lam
= find_location_markers (location
);
154 /* a location that isn't "marked" with markers */
158 lam
->set_name (location
->name());
159 lam
->set_position (location
->start(), location
->end());
161 if (location
->is_auto_loop()) {
162 update_loop_range_view ();
163 } else if (location
->is_auto_punch()) {
164 update_punch_range_view ();
169 Editor::location_flags_changed (Location
*location
, void *src
)
171 ENSURE_GUI_THREAD(bind (mem_fun(*this, &Editor::location_flags_changed
), location
, src
));
173 LocationMarkers
*lam
= find_location_markers (location
);
176 /* a location that isn't "marked" with markers */
180 // move cd markers to/from cd marker bar as appropriate
181 ensure_cd_marker_updated (lam
, location
);
183 if (location
->is_cd_marker()) {
184 lam
->set_color_rgba (location_cd_marker_color
);
185 } else if (location
->is_mark()) {
186 lam
->set_color_rgba (location_marker_color
);
187 } else if (location
->is_auto_punch()) {
188 lam
->set_color_rgba (location_punch_color
);
189 } else if (location
->is_auto_loop()) {
190 lam
->set_color_rgba (location_loop_color
);
192 lam
->set_color_rgba (location_range_color
);
195 if (location
->is_hidden()) {
202 void Editor::update_cd_marker_display ()
204 for (LocationMarkerMap::iterator i
= location_markers
.begin(); i
!= location_markers
.end(); ++i
) {
205 LocationMarkers
* lam
= i
->second
;
206 Location
* location
= i
->first
;
208 ensure_cd_marker_updated (lam
, location
);
212 void Editor::ensure_cd_marker_updated (LocationMarkers
* lam
, Location
* location
)
214 if (location
->is_cd_marker()
215 && (ruler_cd_marker_action
->get_active() && lam
->start
->get_parent() != cd_marker_group
))
217 //cerr << "reparenting non-cd marker so it can be relocated: " << location->name() << endl;
219 lam
->start
->reparent (*cd_marker_group
);
222 lam
->end
->reparent (*cd_marker_group
);
225 else if ( (!location
->is_cd_marker() || !ruler_cd_marker_action
->get_active())
226 && (lam
->start
->get_parent() == cd_marker_group
))
228 //cerr << "reparenting non-cd marker so it can be relocated: " << location->name() << endl;
229 if (location
->is_mark()) {
231 lam
->start
->reparent (*marker_group
);
234 lam
->end
->reparent (*marker_group
);
239 lam
->start
->reparent (*range_marker_group
);
242 lam
->end
->reparent (*range_marker_group
);
248 Editor::LocationMarkers::~LocationMarkers ()
259 Editor::LocationMarkers
*
260 Editor::find_location_markers (Location
*location
) const
262 LocationMarkerMap::const_iterator i
;
264 for (i
= location_markers
.begin(); i
!= location_markers
.end(); ++i
) {
265 if ((*i
).first
== location
) {
274 Editor::find_location_from_marker (Marker
*marker
, bool& is_start
) const
276 LocationMarkerMap::const_iterator i
;
278 for (i
= location_markers
.begin(); i
!= location_markers
.end(); ++i
) {
279 LocationMarkers
*lm
= (*i
).second
;
280 if (lm
->start
== marker
) {
283 } else if (lm
->end
== marker
) {
293 Editor::refresh_location_display_internal (Locations::LocationList
& locations
)
297 for (LocationMarkerMap::iterator i
= location_markers
.begin(); i
!= location_markers
.end(); ++i
) {
298 i
->second
->valid
= false;
303 for (Locations::LocationList::iterator i
= locations
.begin(); i
!= locations
.end(); ++i
) {
305 LocationMarkerMap::iterator x
;
307 if ((x
= location_markers
.find (*i
)) != location_markers
.end()) {
308 x
->second
->valid
= true;
312 add_new_location (*i
);
315 /* remove dead ones */
317 for (LocationMarkerMap::iterator i
= location_markers
.begin(); i
!= location_markers
.end(); ) {
319 LocationMarkerMap::iterator tmp
;
324 if (!i
->second
->valid
) {
326 location_markers
.erase (i
);
332 update_punch_range_view (false);
333 update_loop_range_view (false);
337 Editor::refresh_location_display ()
339 ENSURE_GUI_THREAD(mem_fun(*this, &Editor::refresh_location_display
));
342 session
->locations()->apply (*this, &Editor::refresh_location_display_internal
);
347 Editor::refresh_location_display_s (Change ignored
)
349 ENSURE_GUI_THREAD(bind (mem_fun(*this, &Editor::refresh_location_display_s
), ignored
));
352 session
->locations()->apply (*this, &Editor::refresh_location_display_internal
);
357 Editor::LocationMarkers::hide()
360 if (end
) { end
->hide(); }
364 Editor::LocationMarkers::show()
367 if (end
) { end
->show(); }
371 Editor::LocationMarkers::set_name (const string
& str
)
373 start
->set_name (str
);
374 if (end
) { end
->set_name (str
); }
378 Editor::LocationMarkers::set_position (nframes64_t startf
,
381 start
->set_position (startf
);
382 if (end
) { end
->set_position (endf
); }
386 Editor::LocationMarkers::set_color_rgba (uint32_t rgba
)
388 start
->set_color_rgba (rgba
);
389 if (end
) { end
->set_color_rgba (rgba
); }
393 Editor::mouse_add_new_marker (nframes64_t where
, bool is_cd
, bool is_xrun
)
395 string markername
, markerprefix
;
396 int flags
= (is_cd
? Location::IsCDMarker
|Location::IsMark
: Location::IsMark
);
399 markerprefix
= "xrun";
400 flags
= Location::IsMark
;
402 markerprefix
= "mark";
406 session
->locations()->next_available_name(markername
, markerprefix
);
407 if (!is_xrun
&& !choose_new_marker_name(markername
)) {
410 Location
*location
= new Location (where
, where
, markername
, (Location::Flags
) flags
);
411 session
->begin_reversible_command (_("add marker"));
412 XMLNode
&before
= session
->locations()->get_state();
413 session
->locations()->add (location
, true);
414 XMLNode
&after
= session
->locations()->get_state();
415 session
->add_command (new MementoCommand
<Locations
>(*(session
->locations()), &before
, &after
));
416 session
->commit_reversible_command ();
418 /* find the marker we just added */
420 LocationMarkers
*lam
= find_location_markers (location
);
422 /* make it the selected marker */
423 selection
->set (lam
->start
);
429 Editor::remove_marker (ArdourCanvas::Item
& item
, GdkEvent
* event
)
434 if ((marker
= static_cast<Marker
*> (item
.get_data ("marker"))) == 0) {
435 fatal
<< _("programming error: marker canvas item has no marker object pointer!") << endmsg
;
439 if (entered_marker
== marker
) {
440 entered_marker
= NULL
;
443 Location
* loc
= find_location_from_marker (marker
, is_start
);
445 if (session
&& loc
) {
446 Glib::signal_idle().connect (bind (mem_fun(*this, &Editor::really_remove_marker
), loc
));
451 Editor::really_remove_marker (Location
* loc
)
453 session
->begin_reversible_command (_("remove marker"));
454 XMLNode
&before
= session
->locations()->get_state();
455 session
->locations()->remove (loc
);
456 XMLNode
&after
= session
->locations()->get_state();
457 session
->add_command (new MementoCommand
<Locations
>(*(session
->locations()), &before
, &after
));
458 session
->commit_reversible_command ();
463 Editor::location_gone (Location
*location
)
465 ENSURE_GUI_THREAD(bind (mem_fun(*this, &Editor::location_gone
), location
));
467 LocationMarkerMap::iterator i
;
469 if (location
== transport_loop_location()) {
470 update_loop_range_view (true);
473 if (location
== transport_punch_location()) {
474 update_punch_range_view (true);
477 for (i
= location_markers
.begin(); i
!= location_markers
.end(); ++i
) {
478 if ((*i
).first
== location
) {
480 location_markers
.erase (i
);
487 Editor::tm_marker_context_menu (GdkEventButton
* ev
, ArdourCanvas::Item
* item
)
489 if (tm_marker_menu
== 0) {
490 build_tm_marker_menu ();
493 marker_menu_item
= item
;
494 tm_marker_menu
->popup (1, ev
->time
);
499 Editor::marker_context_menu (GdkEventButton
* ev
, ArdourCanvas::Item
* item
)
502 if ((marker
= reinterpret_cast<Marker
*> (item
->get_data("marker"))) == 0) {
503 fatal
<< _("programming error: marker canvas item has no marker object pointer!") << endmsg
;
508 Location
* loc
= find_location_from_marker (marker
, is_start
);
509 if (loc
== transport_loop_location() || loc
== transport_punch_location()) {
510 if (transport_marker_menu
== 0) {
511 build_range_marker_menu (true);
513 marker_menu_item
= item
;
514 transport_marker_menu
->popup (1, ev
->time
);
517 if (loc
->is_mark()) {
518 bool start_or_end
= loc
->is_start() || loc
->is_end();
521 if (start_end_marker_menu
== 0)
522 build_marker_menu (true);
523 markerMenu
= start_end_marker_menu
;
525 if (marker_menu
== 0)
526 build_marker_menu (false);
527 markerMenu
= marker_menu
;
531 // GTK2FIX use action group sensitivity
533 if (children
.size() >= 3) {
534 MenuItem
* loopitem
= &children
[2];
536 if (loc
->is_mark()) {
537 loopitem
->set_sensitive(false);
540 loopitem
->set_sensitive(true);
545 marker_menu_item
= item
;
546 markerMenu
->popup (1, ev
->time
);
549 if (loc
->is_range_marker()) {
550 if (range_marker_menu
== 0){
551 build_range_marker_menu (false);
553 marker_menu_item
= item
;
554 range_marker_menu
->popup (1, ev
->time
);
560 Editor::new_transport_marker_context_menu (GdkEventButton
* ev
, ArdourCanvas::Item
* item
)
562 if (new_transport_marker_menu
== 0) {
563 build_new_transport_marker_menu ();
566 new_transport_marker_menu
->popup (1, ev
->time
);
571 Editor::transport_marker_context_menu (GdkEventButton
* ev
, ArdourCanvas::Item
* item
)
573 if (transport_marker_menu
== 0) {
574 build_range_marker_menu (true);
577 transport_marker_menu
->popup (1, ev
->time
);
581 Editor::build_marker_menu (bool start_or_end
)
583 using namespace Menu_Helpers
;
585 Menu
*markerMenu
= new Menu
;
587 start_end_marker_menu
= markerMenu
;
589 marker_menu
= markerMenu
;
591 MenuList
& items
= markerMenu
->items();
592 markerMenu
->set_name ("ArdourContextMenu");
594 items
.push_back (MenuElem (_("Locate to here"), mem_fun(*this, &Editor::marker_menu_set_playhead
)));
595 items
.push_back (MenuElem (_("Play from here"), mem_fun(*this, &Editor::marker_menu_play_from
)));
596 items
.push_back (MenuElem (_("Move Mark to Playhead"), mem_fun(*this, &Editor::marker_menu_set_from_playhead
)));
598 items
.push_back (SeparatorElem());
600 items
.push_back (MenuElem (_("Create range to next marker"), mem_fun(*this, &Editor::marker_menu_range_to_next
)));
602 items
.push_back (MenuElem (_("Hide"), mem_fun(*this, &Editor::marker_menu_hide
)));
603 if (start_or_end
) return;
604 items
.push_back (MenuElem (_("Rename"), mem_fun(*this, &Editor::marker_menu_rename
)));
605 items
.push_back (MenuElem (_("Lock"), bind (mem_fun(*this, &Editor::marker_menu_lock
), true)));
606 items
.push_back (MenuElem (_("Unlock"), bind (mem_fun(*this, &Editor::marker_menu_lock
), false)));
608 items
.push_back (SeparatorElem());
610 items
.push_back (MenuElem (_("Remove"), mem_fun(*this, &Editor::marker_menu_remove
)));
614 Editor::build_range_marker_menu (bool loop_or_punch
)
616 using namespace Menu_Helpers
;
618 Menu
*markerMenu
= new Menu
;
620 transport_marker_menu
= markerMenu
;
622 range_marker_menu
= markerMenu
;
625 MenuList
& items
= markerMenu
->items();
626 markerMenu
->set_name ("ArdourContextMenu");
628 items
.push_back (MenuElem (_("Play Range"), mem_fun(*this, &Editor::marker_menu_play_range
)));
629 items
.push_back (MenuElem (_("Locate to Range Mark"), mem_fun(*this, &Editor::marker_menu_set_playhead
)));
630 items
.push_back (MenuElem (_("Play from Range Mark"), mem_fun(*this, &Editor::marker_menu_play_from
)));
631 if (!loop_or_punch
) {
632 items
.push_back (MenuElem (_("Loop Range"), mem_fun(*this, &Editor::marker_menu_loop_range
)));
634 items
.push_back (MenuElem (_("Set Range Mark from Playhead"), mem_fun(*this, &Editor::marker_menu_set_from_playhead
)));
635 if (!Profile
->get_sae()) {
636 items
.push_back (MenuElem (_("Set Range from Range Selection"), mem_fun(*this, &Editor::marker_menu_set_from_selection
)));
639 items
.push_back (SeparatorElem());
641 items
.push_back (MenuElem (_("Export Range"), mem_fun(*this, &Editor::marker_menu_export_range
)));
643 items
.push_back (SeparatorElem());
645 if (!loop_or_punch
) {
646 items
.push_back (MenuElem (_("Hide Range"), mem_fun(*this, &Editor::marker_menu_hide
)));
647 items
.push_back (MenuElem (_("Rename Range"), mem_fun(*this, &Editor::marker_menu_rename
)));
648 items
.push_back (MenuElem (_("Remove Range"), mem_fun(*this, &Editor::marker_menu_remove
)));
651 items
.push_back (SeparatorElem());
653 items
.push_back (MenuElem (_("Separate Regions in Range"), mem_fun(*this, &Editor::marker_menu_separate_regions_using_location
)));
654 items
.push_back (MenuElem (_("Select All in Range"), mem_fun(*this, &Editor::marker_menu_select_all_selectables_using_range
)));
655 if (!Profile
->get_sae()) {
656 items
.push_back (MenuElem (_("Select Range"), mem_fun(*this, &Editor::marker_menu_select_using_range
)));
661 Editor::build_tm_marker_menu ()
663 using namespace Menu_Helpers
;
665 tm_marker_menu
= new Menu
;
666 MenuList
& items
= tm_marker_menu
->items();
667 tm_marker_menu
->set_name ("ArdourContextMenu");
669 items
.push_back (MenuElem (_("Edit"), mem_fun(*this, &Editor::marker_menu_edit
)));
670 items
.push_back (MenuElem (_("Remove"), mem_fun(*this, &Editor::marker_menu_remove
)));
674 Editor::build_new_transport_marker_menu ()
676 using namespace Menu_Helpers
;
678 new_transport_marker_menu
= new Menu
;
679 MenuList
& items
= new_transport_marker_menu
->items();
680 new_transport_marker_menu
->set_name ("ArdourContextMenu");
682 items
.push_back (MenuElem (_("Set Loop Range"), mem_fun(*this, &Editor::new_transport_marker_menu_set_loop
)));
683 items
.push_back (MenuElem (_("Set Punch Range"), mem_fun(*this, &Editor::new_transport_marker_menu_set_punch
)));
685 new_transport_marker_menu
->signal_unmap().connect ( mem_fun(*this, &Editor::new_transport_marker_menu_popdown
));
689 Editor::marker_menu_hide ()
693 if ((marker
= reinterpret_cast<Marker
*> (marker_menu_item
->get_data ("marker"))) == 0) {
694 fatal
<< _("programming error: marker canvas item has no marker object pointer!") << endmsg
;
701 if ((l
= find_location_from_marker (marker
, is_start
)) != 0) {
702 l
->set_hidden (true, this);
707 Editor::marker_menu_select_using_range ()
711 if ((marker
= reinterpret_cast<Marker
*> (marker_menu_item
->get_data ("marker"))) == 0) {
712 fatal
<< _("programming error: marker canvas item has no marker object pointer!") << endmsg
;
719 if (((l
= find_location_from_marker (marker
, is_start
)) != 0) && (l
->end() > l
->start())) {
720 set_selection_from_range (*l
);
725 Editor::marker_menu_select_all_selectables_using_range ()
729 if ((marker
= reinterpret_cast<Marker
*> (marker_menu_item
->get_data ("marker"))) == 0) {
730 fatal
<< _("programming error: marker canvas item has no marker object pointer!") << endmsg
;
737 if (((l
= find_location_from_marker (marker
, is_start
)) != 0) && (l
->end() > l
->start())) {
738 select_all_within (l
->start(), l
->end() - 1, 0, DBL_MAX
, track_views
, Selection::Set
);
744 Editor::marker_menu_separate_regions_using_location ()
748 if ((marker
= reinterpret_cast<Marker
*> (marker_menu_item
->get_data ("marker"))) == 0) {
749 fatal
<< _("programming error: marker canvas item has no marker object pointer!") << endmsg
;
756 if (((l
= find_location_from_marker (marker
, is_start
)) != 0) && (l
->end() > l
->start())) {
757 separate_regions_using_location (*l
);
763 Editor::marker_menu_play_from ()
767 if ((marker
= reinterpret_cast<Marker
*> (marker_menu_item
->get_data ("marker"))) == 0) {
768 fatal
<< _("programming error: marker canvas item has no marker object pointer!") << endmsg
;
775 if ((l
= find_location_from_marker (marker
, is_start
)) != 0) {
778 session
->request_locate (l
->start(), true);
781 //session->request_bounded_roll (l->start(), l->end());
784 session
->request_locate (l
->start(), true);
786 session
->request_locate (l
->end(), true);
793 Editor::marker_menu_set_playhead ()
797 if ((marker
= reinterpret_cast<Marker
*> (marker_menu_item
->get_data ("marker"))) == 0) {
798 fatal
<< _("programming error: marker canvas item has no marker object pointer!") << endmsg
;
805 if ((l
= find_location_from_marker (marker
, is_start
)) != 0) {
808 session
->request_locate (l
->start(), false);
812 session
->request_locate (l
->start(), false);
814 session
->request_locate (l
->end(), false);
821 Editor::marker_menu_export_range ()
825 if ((marker
= reinterpret_cast<Marker
*> (marker_menu_item
->get_data ("marker"))) == 0) {
826 fatal
<< _("programming error: marker canvas item has no marker object pointer!") << endmsg
;
833 if ((l
= find_location_from_marker (marker
, is_start
)) != 0) {
834 if (l
->is_range_marker()) {
835 export_range (l
->start(), l
->end());
841 Editor::marker_menu_range_to_next ()
848 if ((marker
= reinterpret_cast<Marker
*> (marker_menu_item
->get_data ("marker"))) == 0) {
849 fatal
<< _("programming error: marker canvas item has no marker object pointer!") << endmsg
;
856 if ((l
= find_location_from_marker (marker
, is_start
)) == 0) {
860 nframes_t end
= session
->locations()->first_mark_after (marker
->position());
862 if (end
!= max_frames
) {
863 string range_name
= l
->name();
864 range_name
+= "-range";
866 Location
* newrange
= new Location (marker
->position(), end
, range_name
, Location::IsRangeMarker
);
867 session
->locations()->add (newrange
);
872 Editor::marker_menu_set_from_playhead ()
876 if ((marker
= reinterpret_cast<Marker
*> (marker_menu_item
->get_data ("marker"))) == 0) {
877 fatal
<< _("programming error: marker canvas item has no marker object pointer!") << endmsg
;
884 if ((l
= find_location_from_marker (marker
, is_start
)) != 0) {
887 l
->set_start (session
->audible_frame ());
891 l
->set_start (session
->audible_frame ());
893 l
->set_end (session
->audible_frame ());
900 Editor::marker_menu_set_from_selection ()
904 if ((marker
= reinterpret_cast<Marker
*> (marker_menu_item
->get_data ("marker"))) == 0) {
905 fatal
<< _("programming error: marker canvas item has no marker object pointer!") << endmsg
;
912 if ((l
= find_location_from_marker (marker
, is_start
)) != 0) {
918 /* if range selection use first to last */
920 if (mouse_mode
== Editing::MouseRange
) {
921 if (!selection
->time
.empty()) {
922 l
->set_start (selection
->time
.start());
923 l
->set_end (selection
->time
.end_frame());
927 if (!selection
->regions
.empty()) {
928 l
->set_start (selection
->regions
.start());
929 l
->set_end (selection
->regions
.end_frame());
938 Editor::marker_menu_play_range ()
942 if ((marker
= reinterpret_cast<Marker
*> (marker_menu_item
->get_data ("marker"))) == 0) {
943 fatal
<< _("programming error: marker canvas item has no marker object pointer!") << endmsg
;
950 if ((l
= find_location_from_marker (marker
, is_start
)) != 0) {
953 session
->request_locate (l
->start(), true);
956 session
->request_bounded_roll (l
->start(), l
->end());
963 Editor::marker_menu_loop_range ()
967 if ((marker
= reinterpret_cast<Marker
*> (marker_menu_item
->get_data ("marker"))) == 0) {
968 fatal
<< _("programming error: marker canvas item has no marker object pointer!") << endmsg
;
975 if ((l
= find_location_from_marker (marker
, is_start
)) != 0) {
977 if ((l2
= transport_loop_location()) != 0) {
978 l2
->set (l
->start(), l
->end());
980 // enable looping, reposition and start rolling
981 session
->request_play_loop(true);
982 session
->request_locate (l2
->start(), true);
988 Editor::marker_menu_edit ()
994 if ((marker
= reinterpret_cast<Marker
*> (marker_menu_item
->get_data ("marker"))) == 0) {
995 fatal
<< _("programming error: marker canvas item has no marker object pointer!") << endmsg
;
999 if ((mm
= dynamic_cast<MeterMarker
*> (marker
)) != 0) {
1000 edit_meter_section (&mm
->meter());
1001 } else if ((tm
= dynamic_cast<TempoMarker
*> (marker
)) != 0) {
1002 edit_tempo_section (&tm
->tempo());
1004 fatal
<< X_("programming erorr: unhandled marker type in Editor::marker_menu_edit")
1011 Editor::marker_menu_remove ()
1017 if ((marker
= reinterpret_cast<Marker
*> (marker_menu_item
->get_data ("marker"))) == 0) {
1018 fatal
<< _("programming error: marker canvas item has no marker object pointer!") << endmsg
;
1022 if ((mm
= dynamic_cast<MeterMarker
*> (marker
)) != 0) {
1023 remove_meter_marker (marker_menu_item
);
1024 } else if ((tm
= dynamic_cast<TempoMarker
*> (marker
)) != 0) {
1025 remove_tempo_marker (marker_menu_item
);
1027 remove_marker (*marker_menu_item
, (GdkEvent
*) 0);
1032 Editor::marker_menu_lock (bool yn
)
1037 if ((marker
= reinterpret_cast<Marker
*> (marker_menu_item
->get_data ("marker"))) == 0) {
1038 fatal
<< _("programming error: marker canvas item has no marker object pointer!") << endmsg
;
1045 loc
= find_location_from_marker (marker
, ignored
);
1057 Editor::marker_menu_rename ()
1061 if ((marker
= reinterpret_cast<Marker
*> (marker_menu_item
->get_data ("marker"))) == 0) {
1062 fatal
<< _("programming error: marker canvas item has no marker object pointer!") << endmsg
;
1069 loc
= find_location_from_marker (marker
, is_start
);
1073 ArdourPrompter
dialog (true);
1076 dialog
.set_prompt (_("New Name:"));
1078 WindowTitle
title(Glib::get_application_name());
1079 if (loc
->is_mark()) {
1080 title
+= _("Rename Mark");
1082 title
+= _("Rename Range");
1085 dialog
.set_title(title
.get_string());
1087 dialog
.set_name ("MarkRenameWindow");
1088 dialog
.set_size_request (250, -1);
1089 dialog
.set_position (Gtk::WIN_POS_MOUSE
);
1091 dialog
.add_button (_("Rename"), RESPONSE_ACCEPT
);
1092 dialog
.set_response_sensitive (Gtk::RESPONSE_ACCEPT
, false);
1093 dialog
.set_initial_text (loc
->name());
1097 switch (dialog
.run ()) {
1098 case RESPONSE_ACCEPT
:
1104 begin_reversible_command ( _("rename marker") );
1105 XMLNode
&before
= session
->locations()->get_state();
1107 dialog
.get_result(txt
);
1108 loc
->set_name (txt
);
1110 XMLNode
&after
= session
->locations()->get_state();
1111 session
->add_command (new MementoCommand
<Locations
>(*(session
->locations()), &before
, &after
));
1112 commit_reversible_command ();
1116 Editor::new_transport_marker_menu_popdown ()
1119 transport_bar_drag_rect
->hide();
1120 range_marker_drag_rect
->hide();
1124 Editor::new_transport_marker_menu_set_loop ()
1126 set_loop_range (temp_location
->start(), temp_location
->end(), _("set loop range"));
1130 Editor::new_transport_marker_menu_set_punch ()
1132 set_punch_range (temp_location
->start(), temp_location
->end(), _("set punch range"));
1136 Editor::update_loop_range_view (bool visibility
)
1144 if (session
->get_play_loop() && ((tll
= transport_loop_location()) != 0)) {
1146 double x1
= frame_to_pixel (tll
->start());
1147 double x2
= frame_to_pixel (tll
->end());
1149 transport_loop_range_rect
->property_x1() = x1
;
1150 transport_loop_range_rect
->property_x2() = x2
;
1153 transport_loop_range_rect
->show();
1156 } else if (visibility
) {
1157 transport_loop_range_rect
->hide();
1162 Editor::update_punch_range_view (bool visibility
)
1170 if ((Config
->get_punch_in() || Config
->get_punch_out()) && ((tpl
= transport_punch_location()) != 0)) {
1171 guint track_canvas_width
,track_canvas_height
;
1172 track_canvas
->get_size(track_canvas_width
,track_canvas_height
);
1173 if (Config
->get_punch_in()) {
1174 transport_punch_range_rect
->property_x1() = frame_to_pixel (tpl
->start());
1175 transport_punch_range_rect
->property_x2() = (Config
->get_punch_out() ? frame_to_pixel (tpl
->end()) : frame_to_pixel (JACK_MAX_FRAMES
));
1177 transport_punch_range_rect
->property_x1() = 0;
1178 transport_punch_range_rect
->property_x2() = (Config
->get_punch_out() ? frame_to_pixel (tpl
->end()) : track_canvas_width
);
1182 transport_punch_range_rect
->show();
1184 } else if (visibility
) {
1185 transport_punch_range_rect
->hide();
1190 Editor::marker_selection_changed ()
1192 if (session
&& session
->deletion_in_progress()) {
1196 for (LocationMarkerMap::iterator i
= location_markers
.begin(); i
!= location_markers
.end(); ++i
) {
1197 LocationMarkers
* lam
= i
->second
;
1200 lam
->start
->hide_line();
1204 lam
->end
->hide_line();
1208 edit_point_clock_connection_a
.disconnect();
1209 edit_point_clock_connection_b
.disconnect();
1211 if (selection
->markers
.empty()) {
1212 edit_point_clock
.set (0);
1216 for (MarkerSelection::iterator x
= selection
->markers
.begin(); x
!= selection
->markers
.end(); ++x
) {
1217 (*x
)->add_line (cursor_group
, 0, canvas_height
);
1221 edit_point_clock
.set (selection
->markers
.front()->position());
1224 Location
* loc
= find_location_from_marker (selection
->markers
.front(), ignored
);
1227 edit_point_clock_connection_a
= loc
->changed
.connect (mem_fun (*this, &Editor::selected_marker_moved
));
1228 edit_point_clock_connection_b
= loc
->start_changed
.connect (mem_fun (*this, &Editor::selected_marker_moved
));
1233 Editor::selected_marker_moved (Location
* loc
)
1235 edit_point_clock
.set (loc
->start());
1238 struct SortLocationsByPosition
{
1239 bool operator() (Location
* a
, Location
* b
) {
1240 return a
->start() < b
->start();
1245 Editor::goto_nth_marker (int n
)
1250 const Locations::LocationList
& l (session
->locations()->list());
1251 Locations::LocationList ordered
;
1254 SortLocationsByPosition cmp
;
1257 for (Locations::LocationList::iterator i
= ordered
.begin(); n
>= 0 && i
!= ordered
.end(); ++i
) {
1258 if ((*i
)->is_mark() && !(*i
)->is_hidden() && !(*i
)->is_start()) {
1260 session
->request_locate ((*i
)->start(), session
->transport_rolling());