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>
27 #include "ardour/location.h"
28 #include "ardour/profile.h"
29 #include "pbd/memento_command.h"
33 #include "selection.h"
35 #include "gui_thread.h"
36 #include "simplerect.h"
44 using namespace ARDOUR
;
47 using namespace Gtkmm2ext
;
50 Editor::clear_marker_display ()
52 for (LocationMarkerMap::iterator i
= location_markers
.begin(); i
!= location_markers
.end(); ++i
) {
56 location_markers
.clear ();
60 Editor::add_new_location (Location
*location
)
62 ENSURE_GUI_THREAD (bind (mem_fun(*this, &Editor::add_new_location
), location
));
64 LocationMarkers
*lam
= new LocationMarkers
;
67 if (location
->is_cd_marker()) {
68 color
= location_cd_marker_color
;
69 } else if (location
->is_mark()) {
70 color
= location_marker_color
;
71 } else if (location
->is_auto_loop()) {
72 color
= location_loop_color
;
73 } else if (location
->is_auto_punch()) {
74 color
= location_punch_color
;
76 color
= location_range_color
;
79 if (location
->is_mark()) {
81 if (location
->is_cd_marker() && ruler_cd_marker_action
->get_active()) {
82 lam
->start
= new Marker (*this, *cd_marker_group
, color
, location
->name(), Marker::Mark
, location
->start());
85 lam
->start
= new Marker (*this, *marker_group
, color
, location
->name(), Marker::Mark
, location
->start());
89 } else if (location
->is_auto_loop()) {
91 lam
->start
= new Marker (*this, *transport_marker_group
, color
,
92 location
->name(), Marker::LoopStart
, location
->start());
93 lam
->end
= new Marker (*this, *transport_marker_group
, color
,
94 location
->name(), Marker::LoopEnd
, location
->end());
96 } else if (location
->is_auto_punch()) {
98 lam
->start
= new Marker (*this, *transport_marker_group
, color
,
99 location
->name(), Marker::PunchIn
, location
->start());
100 lam
->end
= new Marker (*this, *transport_marker_group
, color
,
101 location
->name(), Marker::PunchOut
, location
->end());
105 if (location
->is_cd_marker() && ruler_cd_marker_action
->get_active()) {
106 lam
->start
= new Marker (*this, *cd_marker_group
, color
,
107 location
->name(), Marker::Start
, location
->start());
108 lam
->end
= new Marker (*this, *cd_marker_group
, color
,
109 location
->name(), Marker::End
, location
->end());
113 lam
->start
= new Marker (*this, *range_marker_group
, color
,
114 location
->name(), Marker::Start
, location
->start());
115 lam
->end
= new Marker (*this, *range_marker_group
, color
,
116 location
->name(), Marker::End
, location
->end());
120 if (location
->is_hidden ()) {
126 location
->start_changed
.connect (mem_fun(*this, &Editor::location_changed
));
127 location
->end_changed
.connect (mem_fun(*this, &Editor::location_changed
));
128 location
->changed
.connect (mem_fun(*this, &Editor::location_changed
));
129 location
->name_changed
.connect (mem_fun(*this, &Editor::location_changed
));
130 location
->FlagsChanged
.connect (mem_fun(*this, &Editor::location_flags_changed
));
132 pair
<Location
*,LocationMarkers
*> newpair
;
134 newpair
.first
= location
;
135 newpair
.second
= lam
;
137 location_markers
.insert (newpair
);
139 if (select_new_marker
&& location
->is_mark()) {
140 selection
->set (lam
->start
);
141 select_new_marker
= false;
146 Editor::location_changed (Location
*location
)
148 ENSURE_GUI_THREAD (bind (mem_fun(*this, &Editor::location_changed
), location
));
150 LocationMarkers
*lam
= find_location_markers (location
);
153 /* a location that isn't "marked" with markers */
157 lam
->set_name (location
->name());
158 lam
->set_position (location
->start(), location
->end());
160 if (location
->is_auto_loop()) {
161 update_loop_range_view ();
162 } else if (location
->is_auto_punch()) {
163 update_punch_range_view ();
168 Editor::location_flags_changed (Location
*location
, void *src
)
170 ENSURE_GUI_THREAD(bind (mem_fun(*this, &Editor::location_flags_changed
), location
, src
));
172 LocationMarkers
*lam
= find_location_markers (location
);
175 /* a location that isn't "marked" with markers */
179 // move cd markers to/from cd marker bar as appropriate
180 ensure_cd_marker_updated (lam
, location
);
182 if (location
->is_cd_marker()) {
183 lam
->set_color_rgba (location_cd_marker_color
);
184 } else if (location
->is_mark()) {
185 lam
->set_color_rgba (location_marker_color
);
186 } else if (location
->is_auto_punch()) {
187 lam
->set_color_rgba (location_punch_color
);
188 } else if (location
->is_auto_loop()) {
189 lam
->set_color_rgba (location_loop_color
);
191 lam
->set_color_rgba (location_range_color
);
194 if (location
->is_hidden()) {
201 void Editor::update_cd_marker_display ()
203 for (LocationMarkerMap::iterator i
= location_markers
.begin(); i
!= location_markers
.end(); ++i
) {
204 LocationMarkers
* lam
= i
->second
;
205 Location
* location
= i
->first
;
207 ensure_cd_marker_updated (lam
, location
);
211 void Editor::ensure_cd_marker_updated (LocationMarkers
* lam
, Location
* location
)
213 if (location
->is_cd_marker()
214 && (ruler_cd_marker_action
->get_active() && lam
->start
->get_parent() != cd_marker_group
))
216 //cerr << "reparenting non-cd marker so it can be relocated: " << location->name() << endl;
218 lam
->start
->reparent (*cd_marker_group
);
221 lam
->end
->reparent (*cd_marker_group
);
224 else if ( (!location
->is_cd_marker() || !ruler_cd_marker_action
->get_active())
225 && (lam
->start
->get_parent() == cd_marker_group
))
227 //cerr << "reparenting non-cd marker so it can be relocated: " << location->name() << endl;
228 if (location
->is_mark()) {
230 lam
->start
->reparent (*marker_group
);
233 lam
->end
->reparent (*marker_group
);
238 lam
->start
->reparent (*range_marker_group
);
241 lam
->end
->reparent (*range_marker_group
);
247 Editor::LocationMarkers::~LocationMarkers ()
253 Editor::LocationMarkers
*
254 Editor::find_location_markers (Location
*location
) const
256 LocationMarkerMap::const_iterator i
;
258 for (i
= location_markers
.begin(); i
!= location_markers
.end(); ++i
) {
259 if ((*i
).first
== location
) {
268 Editor::find_location_from_marker (Marker
*marker
, bool& is_start
) const
270 LocationMarkerMap::const_iterator i
;
272 for (i
= location_markers
.begin(); i
!= location_markers
.end(); ++i
) {
273 LocationMarkers
*lm
= (*i
).second
;
274 if (lm
->start
== marker
) {
277 } else if (lm
->end
== marker
) {
287 Editor::refresh_location_display_internal (Locations::LocationList
& locations
)
291 for (LocationMarkerMap::iterator i
= location_markers
.begin(); i
!= location_markers
.end(); ++i
) {
292 i
->second
->valid
= false;
297 for (Locations::LocationList::iterator i
= locations
.begin(); i
!= locations
.end(); ++i
) {
299 LocationMarkerMap::iterator x
;
301 if ((x
= location_markers
.find (*i
)) != location_markers
.end()) {
302 x
->second
->valid
= true;
306 add_new_location (*i
);
309 /* remove dead ones */
311 for (LocationMarkerMap::iterator i
= location_markers
.begin(); i
!= location_markers
.end(); ) {
313 LocationMarkerMap::iterator tmp
;
318 if (!i
->second
->valid
) {
320 location_markers
.erase (i
);
326 update_punch_range_view (false);
327 update_loop_range_view (false);
331 Editor::refresh_location_display ()
333 ENSURE_GUI_THREAD(mem_fun(*this, &Editor::refresh_location_display
));
336 session
->locations()->apply (*this, &Editor::refresh_location_display_internal
);
341 Editor::refresh_location_display_s (Change ignored
)
343 ENSURE_GUI_THREAD(bind (mem_fun(*this, &Editor::refresh_location_display_s
), ignored
));
346 session
->locations()->apply (*this, &Editor::refresh_location_display_internal
);
351 Editor::LocationMarkers::hide()
354 if (end
) { end
->hide(); }
358 Editor::LocationMarkers::show()
361 if (end
) { end
->show(); }
365 Editor::LocationMarkers::set_name (const string
& str
)
367 start
->set_name (str
);
368 if (end
) { end
->set_name (str
); }
372 Editor::LocationMarkers::set_position (nframes64_t startf
,
375 start
->set_position (startf
);
376 if (end
) { end
->set_position (endf
); }
380 Editor::LocationMarkers::set_color_rgba (uint32_t rgba
)
382 start
->set_color_rgba (rgba
);
383 if (end
) { end
->set_color_rgba (rgba
); }
387 Editor::mouse_add_new_marker (nframes64_t where
, bool is_cd
, bool is_xrun
)
389 string markername
, markerprefix
;
390 int flags
= (is_cd
? Location::IsCDMarker
|Location::IsMark
: Location::IsMark
);
393 markerprefix
= "xrun";
394 flags
= Location::IsMark
;
396 markerprefix
= "mark";
400 session
->locations()->next_available_name(markername
, markerprefix
);
401 if (!is_xrun
&& !choose_new_marker_name(markername
)) {
404 Location
*location
= new Location (where
, where
, markername
, (Location::Flags
) flags
);
405 session
->begin_reversible_command (_("add marker"));
406 XMLNode
&before
= session
->locations()->get_state();
407 session
->locations()->add (location
, true);
408 XMLNode
&after
= session
->locations()->get_state();
409 session
->add_command (new MementoCommand
<Locations
>(*(session
->locations()), &before
, &after
));
410 session
->commit_reversible_command ();
412 /* find the marker we just added */
414 LocationMarkers
*lam
= find_location_markers (location
);
416 /* make it the selected marker */
417 selection
->set (lam
->start
);
423 Editor::remove_marker (ArdourCanvas::Item
& item
, GdkEvent
*)
428 if ((marker
= static_cast<Marker
*> (item
.get_data ("marker"))) == 0) {
429 fatal
<< _("programming error: marker canvas item has no marker object pointer!") << endmsg
;
433 if (entered_marker
== marker
) {
434 entered_marker
= NULL
;
437 Location
* loc
= find_location_from_marker (marker
, is_start
);
439 if (session
&& loc
) {
440 Glib::signal_idle().connect (bind (mem_fun(*this, &Editor::really_remove_marker
), loc
));
445 Editor::really_remove_marker (Location
* loc
)
447 session
->begin_reversible_command (_("remove marker"));
448 XMLNode
&before
= session
->locations()->get_state();
449 session
->locations()->remove (loc
);
450 XMLNode
&after
= session
->locations()->get_state();
451 session
->add_command (new MementoCommand
<Locations
>(*(session
->locations()), &before
, &after
));
452 session
->commit_reversible_command ();
457 Editor::location_gone (Location
*location
)
459 ENSURE_GUI_THREAD(bind (mem_fun(*this, &Editor::location_gone
), location
));
461 LocationMarkerMap::iterator i
;
463 if (location
== transport_loop_location()) {
464 update_loop_range_view (true);
467 if (location
== transport_punch_location()) {
468 update_punch_range_view (true);
471 for (i
= location_markers
.begin(); i
!= location_markers
.end(); ++i
) {
472 if ((*i
).first
== location
) {
474 location_markers
.erase (i
);
481 Editor::tm_marker_context_menu (GdkEventButton
* ev
, ArdourCanvas::Item
* item
)
483 if (tm_marker_menu
== 0) {
484 build_tm_marker_menu ();
487 marker_menu_item
= item
;
488 tm_marker_menu
->popup (1, ev
->time
);
493 Editor::marker_context_menu (GdkEventButton
* ev
, ArdourCanvas::Item
* item
)
496 if ((marker
= reinterpret_cast<Marker
*> (item
->get_data("marker"))) == 0) {
497 fatal
<< _("programming error: marker canvas item has no marker object pointer!") << endmsg
;
502 Location
* loc
= find_location_from_marker (marker
, is_start
);
503 if (loc
== transport_loop_location() || loc
== transport_punch_location()) {
504 if (transport_marker_menu
== 0) {
505 build_range_marker_menu (true);
507 marker_menu_item
= item
;
508 transport_marker_menu
->popup (1, ev
->time
);
511 if (loc
->is_mark()) {
512 bool start_or_end
= loc
->is_start() || loc
->is_end();
515 if (start_end_marker_menu
== 0)
516 build_marker_menu (true);
517 markerMenu
= start_end_marker_menu
;
519 if (marker_menu
== 0)
520 build_marker_menu (false);
521 markerMenu
= marker_menu
;
525 // GTK2FIX use action group sensitivity
527 if (children
.size() >= 3) {
528 MenuItem
* loopitem
= &children
[2];
530 if (loc
->is_mark()) {
531 loopitem
->set_sensitive(false);
534 loopitem
->set_sensitive(true);
539 marker_menu_item
= item
;
540 markerMenu
->popup (1, ev
->time
);
543 if (loc
->is_range_marker()) {
544 if (range_marker_menu
== 0){
545 build_range_marker_menu (false);
547 marker_menu_item
= item
;
548 range_marker_menu
->popup (1, ev
->time
);
554 Editor::new_transport_marker_context_menu (GdkEventButton
* ev
, ArdourCanvas::Item
*)
556 if (new_transport_marker_menu
== 0) {
557 build_new_transport_marker_menu ();
560 new_transport_marker_menu
->popup (1, ev
->time
);
565 Editor::transport_marker_context_menu (GdkEventButton
* ev
, ArdourCanvas::Item
*)
567 if (transport_marker_menu
== 0) {
568 build_range_marker_menu (true);
571 transport_marker_menu
->popup (1, ev
->time
);
575 Editor::build_marker_menu (bool start_or_end
)
577 using namespace Menu_Helpers
;
579 Menu
*markerMenu
= new Menu
;
581 start_end_marker_menu
= markerMenu
;
583 marker_menu
= markerMenu
;
585 MenuList
& items
= markerMenu
->items();
586 markerMenu
->set_name ("ArdourContextMenu");
588 items
.push_back (MenuElem (_("Locate to here"), mem_fun(*this, &Editor::marker_menu_set_playhead
)));
589 items
.push_back (MenuElem (_("Play from here"), mem_fun(*this, &Editor::marker_menu_play_from
)));
590 items
.push_back (MenuElem (_("Move Mark to Playhead"), mem_fun(*this, &Editor::marker_menu_set_from_playhead
)));
592 items
.push_back (SeparatorElem());
594 items
.push_back (MenuElem (_("Create range to next marker"), mem_fun(*this, &Editor::marker_menu_range_to_next
)));
596 items
.push_back (MenuElem (_("Hide"), mem_fun(*this, &Editor::marker_menu_hide
)));
597 if (start_or_end
) return;
598 items
.push_back (MenuElem (_("Rename"), mem_fun(*this, &Editor::marker_menu_rename
)));
599 items
.push_back (MenuElem (_("Lock"), bind (mem_fun(*this, &Editor::marker_menu_lock
), true)));
600 items
.push_back (MenuElem (_("Unlock"), bind (mem_fun(*this, &Editor::marker_menu_lock
), false)));
602 items
.push_back (SeparatorElem());
604 items
.push_back (MenuElem (_("Remove"), mem_fun(*this, &Editor::marker_menu_remove
)));
608 Editor::build_range_marker_menu (bool loop_or_punch
)
610 using namespace Menu_Helpers
;
612 Menu
*markerMenu
= new Menu
;
614 transport_marker_menu
= markerMenu
;
616 range_marker_menu
= markerMenu
;
618 MenuList
& items
= markerMenu
->items();
619 markerMenu
->set_name ("ArdourContextMenu");
621 items
.push_back (MenuElem (_("Play Range"), mem_fun(*this, &Editor::marker_menu_play_range
)));
622 items
.push_back (MenuElem (_("Locate to Range Mark"), mem_fun(*this, &Editor::marker_menu_set_playhead
)));
623 items
.push_back (MenuElem (_("Play from Range Mark"), mem_fun(*this, &Editor::marker_menu_play_from
)));
624 if (! loop_or_punch
) {
625 items
.push_back (MenuElem (_("Loop Range"), mem_fun(*this, &Editor::marker_menu_loop_range
)));
627 items
.push_back (MenuElem (_("Set Range Mark from Playhead"), mem_fun(*this, &Editor::marker_menu_set_from_playhead
)));
628 if (!Profile
->get_sae()) {
629 items
.push_back (MenuElem (_("Set Range from Range Selection"), mem_fun(*this, &Editor::marker_menu_set_from_selection
)));
632 items
.push_back (SeparatorElem());
633 items
.push_back (MenuElem (_("Export Range"), mem_fun(*this, &Editor::export_range
)));
634 items
.push_back (SeparatorElem());
636 if (!loop_or_punch
) {
637 items
.push_back (MenuElem (_("Hide Range"), mem_fun(*this, &Editor::marker_menu_hide
)));
638 items
.push_back (MenuElem (_("Rename Range"), mem_fun(*this, &Editor::marker_menu_rename
)));
639 items
.push_back (MenuElem (_("Remove Range"), mem_fun(*this, &Editor::marker_menu_remove
)));
640 items
.push_back (SeparatorElem());
643 items
.push_back (MenuElem (_("Separate Regions in Range"), mem_fun(*this, &Editor::marker_menu_separate_regions_using_location
)));
644 items
.push_back (MenuElem (_("Select All in Range"), mem_fun(*this, &Editor::marker_menu_select_all_selectables_using_range
)));
645 if (!Profile
->get_sae()) {
646 items
.push_back (MenuElem (_("Select Range"), mem_fun(*this, &Editor::marker_menu_select_using_range
)));
651 Editor::build_tm_marker_menu ()
653 using namespace Menu_Helpers
;
655 tm_marker_menu
= new Menu
;
656 MenuList
& items
= tm_marker_menu
->items();
657 tm_marker_menu
->set_name ("ArdourContextMenu");
659 items
.push_back (MenuElem (_("Edit"), mem_fun(*this, &Editor::marker_menu_edit
)));
660 items
.push_back (MenuElem (_("Remove"), mem_fun(*this, &Editor::marker_menu_remove
)));
664 Editor::build_new_transport_marker_menu ()
666 using namespace Menu_Helpers
;
668 new_transport_marker_menu
= new Menu
;
669 MenuList
& items
= new_transport_marker_menu
->items();
670 new_transport_marker_menu
->set_name ("ArdourContextMenu");
672 items
.push_back (MenuElem (_("Set Loop Range"), mem_fun(*this, &Editor::new_transport_marker_menu_set_loop
)));
673 items
.push_back (MenuElem (_("Set Punch Range"), mem_fun(*this, &Editor::new_transport_marker_menu_set_punch
)));
675 new_transport_marker_menu
->signal_unmap().connect ( mem_fun(*this, &Editor::new_transport_marker_menu_popdown
));
679 Editor::marker_menu_hide ()
683 if ((marker
= reinterpret_cast<Marker
*> (marker_menu_item
->get_data ("marker"))) == 0) {
684 fatal
<< _("programming error: marker canvas item has no marker object pointer!") << endmsg
;
691 if ((l
= find_location_from_marker (marker
, is_start
)) != 0) {
692 l
->set_hidden (true, this);
697 Editor::marker_menu_select_using_range ()
701 if ((marker
= reinterpret_cast<Marker
*> (marker_menu_item
->get_data ("marker"))) == 0) {
702 fatal
<< _("programming error: marker canvas item has no marker object pointer!") << endmsg
;
709 if (((l
= find_location_from_marker (marker
, is_start
)) != 0) && (l
->end() > l
->start())) {
710 set_selection_from_range (*l
);
715 Editor::marker_menu_select_all_selectables_using_range ()
719 if ((marker
= reinterpret_cast<Marker
*> (marker_menu_item
->get_data ("marker"))) == 0) {
720 fatal
<< _("programming error: marker canvas item has no marker object pointer!") << endmsg
;
727 if (((l
= find_location_from_marker (marker
, is_start
)) != 0) && (l
->end() > l
->start())) {
728 select_all_within (l
->start(), l
->end() - 1, 0, DBL_MAX
, track_views
, Selection::Set
);
734 Editor::marker_menu_separate_regions_using_location ()
738 if ((marker
= reinterpret_cast<Marker
*> (marker_menu_item
->get_data ("marker"))) == 0) {
739 fatal
<< _("programming error: marker canvas item has no marker object pointer!") << endmsg
;
746 if (((l
= find_location_from_marker (marker
, is_start
)) != 0) && (l
->end() > l
->start())) {
747 separate_regions_using_location (*l
);
753 Editor::marker_menu_play_from ()
757 if ((marker
= reinterpret_cast<Marker
*> (marker_menu_item
->get_data ("marker"))) == 0) {
758 fatal
<< _("programming error: marker canvas item has no marker object pointer!") << endmsg
;
765 if ((l
= find_location_from_marker (marker
, is_start
)) != 0) {
768 session
->request_locate (l
->start(), true);
771 //session->request_bounded_roll (l->start(), l->end());
774 session
->request_locate (l
->start(), true);
776 session
->request_locate (l
->end(), true);
783 Editor::marker_menu_set_playhead ()
787 if ((marker
= reinterpret_cast<Marker
*> (marker_menu_item
->get_data ("marker"))) == 0) {
788 fatal
<< _("programming error: marker canvas item has no marker object pointer!") << endmsg
;
795 if ((l
= find_location_from_marker (marker
, is_start
)) != 0) {
798 session
->request_locate (l
->start(), false);
802 session
->request_locate (l
->start(), false);
804 session
->request_locate (l
->end(), false);
811 Editor::marker_menu_range_to_next ()
818 if ((marker
= reinterpret_cast<Marker
*> (marker_menu_item
->get_data ("marker"))) == 0) {
819 fatal
<< _("programming error: marker canvas item has no marker object pointer!") << endmsg
;
826 if ((l
= find_location_from_marker (marker
, is_start
)) == 0) {
832 session
->locations()->marks_either_side (marker
->position(), start
, end
);
834 if (end
!= max_frames
) {
835 string range_name
= l
->name();
836 range_name
+= "-range";
838 Location
* newrange
= new Location (marker
->position(), end
, range_name
, Location::IsRangeMarker
);
839 session
->locations()->add (newrange
);
844 Editor::marker_menu_set_from_playhead ()
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) {
859 l
->set_start (session
->audible_frame ());
863 l
->set_start (session
->audible_frame ());
865 l
->set_end (session
->audible_frame ());
872 Editor::marker_menu_set_from_selection ()
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) {
891 /* if range selection use first to last */
893 if (mouse_mode
== Editing::MouseRange
) {
894 if (!selection
->time
.empty()) {
895 l
->set_start (selection
->time
.start());
896 l
->set_end (selection
->time
.end_frame());
900 if (!selection
->regions
.empty()) {
901 l
->set_start (selection
->regions
.start());
902 l
->set_end (selection
->regions
.end_frame());
911 Editor::marker_menu_play_range ()
915 if ((marker
= reinterpret_cast<Marker
*> (marker_menu_item
->get_data ("marker"))) == 0) {
916 fatal
<< _("programming error: marker canvas item has no marker object pointer!") << endmsg
;
923 if ((l
= find_location_from_marker (marker
, is_start
)) != 0) {
926 session
->request_locate (l
->start(), true);
929 session
->request_bounded_roll (l
->start(), l
->end());
936 Editor::marker_menu_loop_range ()
940 if ((marker
= reinterpret_cast<Marker
*> (marker_menu_item
->get_data ("marker"))) == 0) {
941 fatal
<< _("programming error: marker canvas item has no marker object pointer!") << endmsg
;
948 if ((l
= find_location_from_marker (marker
, is_start
)) != 0) {
950 if ((l2
= transport_loop_location()) != 0) {
951 l2
->set (l
->start(), l
->end());
953 // enable looping, reposition and start rolling
954 session
->request_play_loop(true);
955 session
->request_locate (l2
->start(), true);
961 Editor::marker_menu_edit ()
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
;
972 if ((mm
= dynamic_cast<MeterMarker
*> (marker
)) != 0) {
973 edit_meter_section (&mm
->meter());
974 } else if ((tm
= dynamic_cast<TempoMarker
*> (marker
)) != 0) {
975 edit_tempo_section (&tm
->tempo());
977 fatal
<< X_("programming erorr: unhandled marker type in Editor::marker_menu_edit")
984 Editor::marker_menu_remove ()
990 if ((marker
= reinterpret_cast<Marker
*> (marker_menu_item
->get_data ("marker"))) == 0) {
991 fatal
<< _("programming error: marker canvas item has no marker object pointer!") << endmsg
;
995 if ((mm
= dynamic_cast<MeterMarker
*> (marker
)) != 0) {
996 remove_meter_marker (marker_menu_item
);
997 } else if ((tm
= dynamic_cast<TempoMarker
*> (marker
)) != 0) {
998 remove_tempo_marker (marker_menu_item
);
1000 remove_marker (*marker_menu_item
, (GdkEvent
*) 0);
1005 Editor::marker_menu_lock (bool yn
)
1010 if ((marker
= reinterpret_cast<Marker
*> (marker_menu_item
->get_data ("marker"))) == 0) {
1011 fatal
<< _("programming error: marker canvas item has no marker object pointer!") << endmsg
;
1018 loc
= find_location_from_marker (marker
, ignored
);
1030 Editor::marker_menu_rename ()
1034 if ((marker
= reinterpret_cast<Marker
*> (marker_menu_item
->get_data ("marker"))) == 0) {
1035 fatal
<< _("programming error: marker canvas item has no marker object pointer!") << endmsg
;
1042 loc
= find_location_from_marker (marker
, is_start
);
1046 ArdourPrompter
dialog (true);
1049 dialog
.set_prompt (_("New Name:"));
1051 if (loc
->is_mark()) {
1052 dialog
.set_title (_("Rename Mark"));
1054 dialog
.set_title (_("Rename Range"));
1057 dialog
.set_name ("MarkRenameWindow");
1058 dialog
.set_size_request (250, -1);
1059 dialog
.set_position (Gtk::WIN_POS_MOUSE
);
1061 dialog
.add_button (_("Rename"), RESPONSE_ACCEPT
);
1062 dialog
.set_response_sensitive (Gtk::RESPONSE_ACCEPT
, false);
1063 dialog
.set_initial_text (loc
->name());
1067 switch (dialog
.run ()) {
1068 case RESPONSE_ACCEPT
:
1074 begin_reversible_command ( _("rename marker") );
1075 XMLNode
&before
= session
->locations()->get_state();
1077 dialog
.get_result(txt
);
1078 loc
->set_name (txt
);
1080 XMLNode
&after
= session
->locations()->get_state();
1081 session
->add_command (new MementoCommand
<Locations
>(*(session
->locations()), &before
, &after
));
1082 commit_reversible_command ();
1086 Editor::new_transport_marker_menu_popdown ()
1089 transport_bar_drag_rect
->hide();
1095 Editor::new_transport_marker_menu_set_loop ()
1097 set_loop_range (temp_location
->start(), temp_location
->end(), _("set loop range"));
1101 Editor::new_transport_marker_menu_set_punch ()
1103 set_punch_range (temp_location
->start(), temp_location
->end(), _("set punch range"));
1107 Editor::update_loop_range_view (bool visibility
)
1115 if (session
->get_play_loop() && ((tll
= transport_loop_location()) != 0)) {
1117 double x1
= frame_to_pixel (tll
->start());
1118 double x2
= frame_to_pixel (tll
->end());
1120 transport_loop_range_rect
->property_x1() = x1
;
1121 transport_loop_range_rect
->property_x2() = x2
;
1124 transport_loop_range_rect
->show();
1127 } else if (visibility
) {
1128 transport_loop_range_rect
->hide();
1133 Editor::update_punch_range_view (bool visibility
)
1141 if ((session
->config
.get_punch_in() || session
->config
.get_punch_out()) && ((tpl
= transport_punch_location()) != 0)) {
1142 guint track_canvas_width
,track_canvas_height
;
1143 track_canvas
->get_size(track_canvas_width
,track_canvas_height
);
1144 if (session
->config
.get_punch_in()) {
1145 transport_punch_range_rect
->property_x1() = frame_to_pixel (tpl
->start());
1146 transport_punch_range_rect
->property_x2() = (session
->config
.get_punch_out() ? frame_to_pixel (tpl
->end()) : frame_to_pixel (JACK_MAX_FRAMES
));
1148 transport_punch_range_rect
->property_x1() = 0;
1149 transport_punch_range_rect
->property_x2() = (session
->config
.get_punch_out() ? frame_to_pixel (tpl
->end()) : track_canvas_width
);
1153 transport_punch_range_rect
->show();
1155 } else if (visibility
) {
1156 transport_punch_range_rect
->hide();
1161 Editor::marker_selection_changed ()
1163 if (session
&& session
->deletion_in_progress()) {
1167 for (LocationMarkerMap::iterator i
= location_markers
.begin(); i
!= location_markers
.end(); ++i
) {
1168 LocationMarkers
* lam
= i
->second
;
1171 lam
->start
->hide_line();
1175 lam
->end
->hide_line();
1179 edit_point_clock_connection_a
.disconnect();
1180 edit_point_clock_connection_b
.disconnect();
1182 if (selection
->markers
.empty()) {
1183 edit_point_clock
.set (0);
1187 for (MarkerSelection::iterator x
= selection
->markers
.begin(); x
!= selection
->markers
.end(); ++x
) {
1188 (*x
)->add_line (cursor_group
, 0, _canvas_height
);
1192 edit_point_clock
.set (selection
->markers
.front()->position());
1195 Location
* loc
= find_location_from_marker (selection
->markers
.front(), ignored
);
1198 edit_point_clock_connection_a
= loc
->changed
.connect (mem_fun (*this, &Editor::selected_marker_moved
));
1199 edit_point_clock_connection_b
= loc
->start_changed
.connect (mem_fun (*this, &Editor::selected_marker_moved
));
1204 Editor::selected_marker_moved (Location
* loc
)
1206 edit_point_clock
.set (loc
->start());
1209 struct SortLocationsByPosition
{
1210 bool operator() (Location
* a
, Location
* b
) {
1211 return a
->start() < b
->start();
1216 Editor::goto_nth_marker (int n
)
1221 const Locations::LocationList
& l (session
->locations()->list());
1222 Locations::LocationList ordered
;
1225 SortLocationsByPosition cmp
;
1228 for (Locations::LocationList::iterator i
= ordered
.begin(); n
>= 0 && i
!= ordered
.end(); ++i
) {
1229 if ((*i
)->is_mark() && !(*i
)->is_hidden() && !(*i
)->is_start()) {
1231 session
->request_locate ((*i
)->start(), session
->transport_rolling());