Various marker undo fixes.
[ardour.git] / gtk2_ardour / editor_markers.cc
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     $Id$
19 */
20
21 #include <sigc++/retype.h>
22 #include <cstdlib>
23 #include <cmath>
24
25 #include <libgnomecanvas/libgnomecanvas.h>
26 #include <gtkmm2ext/gtk_ui.h>
27
28 #include <ardour/location.h>
29
30 #include "editor.h"
31 #include "marker.h"
32 #include "selection.h"
33 #include "editing.h"
34 #include "gui_thread.h"
35 #include "simplerect.h"
36 #include "actions.h"
37
38 #include "i18n.h"
39
40 using namespace std;
41 using namespace sigc;
42 using namespace ARDOUR;
43 using namespace Gtk;
44
45 void
46 Editor::clear_marker_display ()
47 {
48         for (LocationMarkerMap::iterator i = location_markers.begin(); i != location_markers.end(); ++i) {
49                 delete i->second;
50         }
51
52         location_markers.clear ();
53 }
54
55 void
56 Editor::add_new_location (Location *location)
57 {
58         LocationMarkers *lam = new LocationMarkers;
59         uint32_t color;
60
61         if (location->is_cd_marker()) {
62                 color = location_cd_marker_color;
63         } else if (location->is_mark()) {
64                 color = location_marker_color;
65         } else if (location->is_auto_loop()) {
66                 color = location_loop_color;
67         } else if (location->is_auto_punch()) {
68                 color = location_punch_color;
69         } else {
70                 color = location_range_color;
71         }
72
73         if (location->is_mark()) {
74                 lam->start = new Marker (*this, *marker_group, color, location->name(), Marker::Mark, location->start());
75                 lam->end   = 0;
76
77         } else if (location->is_auto_loop()) {
78                 // transport marker
79                 lam->start = new Marker (*this, *transport_marker_group, color, 
80                                          location->name(), Marker::LoopStart, location->start());
81                 lam->end   = new Marker (*this, *transport_marker_group, color, 
82                                          location->name(), Marker::LoopEnd, location->end());
83                 
84         } else if (location->is_auto_punch()) {
85                 // transport marker
86                 lam->start = new Marker (*this, *transport_marker_group, color, 
87                                          location->name(), Marker::PunchIn, location->start());
88                 lam->end   = new Marker (*this, *transport_marker_group, color, 
89                                          location->name(), Marker::PunchOut, location->end());
90                 
91         } else {
92
93                 // range marker
94                 lam->start = new Marker (*this, *range_marker_group, color, 
95                                          location->name(), Marker::Start, location->start());
96                 lam->end   = new Marker (*this, *range_marker_group, color, 
97                                          location->name(), Marker::End, location->end());
98         }
99
100         if (location->is_hidden ()) {
101                 lam->hide();
102         } else {
103                 lam->show ();
104         }
105
106         location->start_changed.connect (mem_fun(*this, &Editor::location_changed));
107         location->end_changed.connect (mem_fun(*this, &Editor::location_changed));
108         location->changed.connect (mem_fun(*this, &Editor::location_changed));
109         location->name_changed.connect (mem_fun(*this, &Editor::location_changed));
110         location->FlagsChanged.connect (mem_fun(*this, &Editor::location_flags_changed));
111
112         pair<Location*,LocationMarkers*> newpair;
113
114         newpair.first = location;
115         newpair.second = lam;
116
117         location_markers.insert (newpair);
118 }
119
120 void
121 Editor::location_changed (Location *location)
122 {
123         ENSURE_GUI_THREAD (bind (mem_fun(*this, &Editor::location_changed), location));
124
125         LocationMarkers *lam = find_location_markers (location);
126
127         if (lam == 0) {
128                 /* a location that isn't "marked" with markers */
129                 return;
130         }
131         
132         lam->set_name (location->name());
133         lam->set_position (location->start(), location->end());
134
135         if (location->is_auto_loop()) {
136                 update_loop_range_view ();
137         } else if (location->is_auto_punch()) {
138                 update_punch_range_view ();
139         }
140 }
141
142 void
143 Editor::location_flags_changed (Location *location, void *src)
144 {
145         ENSURE_GUI_THREAD(bind (mem_fun(*this, &Editor::location_flags_changed), location, src));
146         
147         LocationMarkers *lam = find_location_markers (location);
148         
149         if (lam == 0) {
150                 /* a location that isn't "marked" with markers */
151                 return;
152         }
153
154         if (location->is_cd_marker()) {
155                 lam->set_color_rgba (location_cd_marker_color);
156         } else if (location->is_mark()) {
157                 lam->set_color_rgba (location_marker_color);
158         } else if (location->is_auto_punch()) {
159                 lam->set_color_rgba (location_punch_color);
160         } else if (location->is_auto_loop()) {
161                 lam->set_color_rgba (location_loop_color);
162         } else {
163                 lam->set_color_rgba (location_range_color);
164         }
165         
166         if (location->is_hidden()) {
167                 lam->hide();
168         } else {
169                 lam->show ();
170         }
171 }
172
173 Editor::LocationMarkers::~LocationMarkers ()
174 {
175         if (start) {
176                 delete start;
177         }
178
179         if (end) {
180                 delete end;
181         }
182 }
183
184 Editor::LocationMarkers *
185 Editor::find_location_markers (Location *location)
186 {
187         LocationMarkerMap::iterator i;
188
189         for (i = location_markers.begin(); i != location_markers.end(); ++i) {
190                 if ((*i).first == location) {
191                         return (*i).second;
192                 }
193         }
194
195         return 0;
196 }
197
198 Location *
199 Editor::find_location_from_marker (Marker *marker, bool& is_start)
200 {
201         LocationMarkerMap::iterator i;
202
203         for (i = location_markers.begin(); i != location_markers.end(); ++i) {
204                 LocationMarkers *lm = (*i).second;
205                 if (lm->start == marker) {
206                         is_start = true;
207                         return (*i).first;
208                 } else if (lm->end == marker) {
209                         is_start = false;
210                         return (*i).first;
211                 }
212         }
213
214         return 0;
215 }
216
217 void
218 Editor::refresh_location_display_internal (Locations::LocationList& locations)
219 {
220         clear_marker_display ();
221         
222         for (Locations::LocationList::iterator i = locations.begin(); i != locations.end(); ++i) {
223                 add_new_location (*i);
224         }
225 }
226
227 void
228 Editor::refresh_location_display ()
229 {
230         ENSURE_GUI_THREAD(mem_fun(*this, &Editor::refresh_location_display));
231         
232         if (session) {
233                 session->locations()->apply (*this, &Editor::refresh_location_display_internal);
234         }
235 }
236
237 void
238 Editor::refresh_location_display_s (Change ignored)
239 {
240         ENSURE_GUI_THREAD(bind (mem_fun(*this, &Editor::refresh_location_display_s), ignored));
241
242         if (session) {
243                 session->locations()->apply (*this, &Editor::refresh_location_display_internal);
244         }
245 }
246
247 void
248 Editor::LocationMarkers::hide() 
249 {
250         start->hide ();
251         if (end) { end->hide(); }
252 }
253
254 void
255 Editor::LocationMarkers::show() 
256 {
257         start->show ();
258         if (end) { end->show(); }
259 }
260
261 void
262 Editor::LocationMarkers::set_name (const string& str) 
263 {
264         start->set_name (str);
265         if (end) { end->set_name (str); }
266 }
267
268 void
269 Editor::LocationMarkers::set_position (jack_nframes_t startf, 
270                                        jack_nframes_t endf) 
271 {
272         start->set_position (startf);
273         if (end) { end->set_position (endf); }
274 }
275
276 void
277 Editor::LocationMarkers::set_color_rgba (uint32_t rgba) 
278 {
279         start->set_color_rgba (rgba);
280         if (end) { end->set_color_rgba (rgba); }
281 }
282
283 void
284 Editor::mouse_add_new_marker (jack_nframes_t where)
285 {
286         if (session) {
287                 Location *location = new Location (where, where, "mark", Location::IsMark);
288                 session->begin_reversible_command (_("add marker"));
289                 session->add_undo (session->locations()->get_memento());
290                 session->locations()->add (location, true);
291                 session->add_redo_no_execute (session->locations()->get_memento());
292                 session->commit_reversible_command ();
293         }
294 }
295
296 void
297 Editor::remove_marker (ArdourCanvas::Item& item, GdkEvent* event)
298 {
299         Marker* marker;
300         bool is_start;
301
302         if ((marker = static_cast<Marker*> (item.get_data ("marker"))) == 0) {
303                 fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg;
304                 /*NOTREACHED*/
305         }
306
307         Location* loc = find_location_from_marker (marker, is_start);
308
309         if (session && loc) {
310                 if (loc->is_end()) {
311                         /* you can't hide or delete this marker */
312                         return;
313                 }
314                 if (loc->is_auto_loop() || loc->is_auto_punch()) {
315                         // just hide them
316                         loc->set_hidden (true, this);
317                 }
318                 else {
319                         Glib::signal_idle().connect (bind (mem_fun(*this, &Editor::really_remove_marker), loc));
320                 }
321         }
322 }
323
324 gint
325 Editor::really_remove_marker (Location* loc)
326 {
327         session->begin_reversible_command (_("remove marker"));
328         session->add_undo (session->locations()->get_memento());
329         session->locations()->remove (loc);
330         session->add_redo_no_execute (session->locations()->get_memento());
331         session->commit_reversible_command ();
332         return FALSE;
333 }
334
335 void
336 Editor::location_gone (Location *location)
337 {
338         ENSURE_GUI_THREAD(bind (mem_fun(*this, &Editor::location_gone), location));
339         
340         LocationMarkerMap::iterator i;
341
342         if (location == transport_loop_location()) {
343                 update_loop_range_view (true);
344         }
345
346         if (location == transport_punch_location()) {
347                 update_punch_range_view (true);
348         }
349         
350         for (i = location_markers.begin(); i != location_markers.end(); ++i) {
351                 if ((*i).first == location) {
352                         delete (*i).second;
353                         location_markers.erase (i);
354                         break;
355                 }
356         }
357 }
358
359 void
360 Editor::tm_marker_context_menu (GdkEventButton* ev, ArdourCanvas::Item* item)
361 {
362         if (tm_marker_menu == 0) {
363                 build_tm_marker_menu ();
364         }
365
366         marker_menu_item = item;
367         tm_marker_menu->popup (1, ev->time);
368
369 }
370
371
372 void
373 Editor::marker_context_menu (GdkEventButton* ev, ArdourCanvas::Item* item)
374 {
375         Marker * marker;
376         if ((marker = reinterpret_cast<Marker *> (item->get_data("marker"))) == 0) {
377                 fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg;
378                 /*NOTREACHED*/
379         }
380         
381         bool is_start;
382         Location * loc = find_location_from_marker (marker, is_start);
383         if (loc == transport_loop_location() || loc == transport_punch_location()) {
384                 if (transport_marker_menu == 0) {
385                         build_transport_marker_menu ();
386                 }
387                 marker_menu_item = item;
388                 transport_marker_menu->popup (1, ev->time);
389         } else {
390                 if (marker_menu == 0) {
391                   if (loc->is_mark()) {
392                         build_marker_menu ();
393                   } else {
394                         build_range_marker_menu ();
395                   }
396                 }
397
398                 // GTK2FIX use action group sensitivity
399 #ifdef GTK2FIX
400                 if (children.size() >= 3) {
401                         MenuItem * loopitem = &children[2];
402                         if (loopitem) {
403                                 if (loc->is_mark()) {
404                                         loopitem->set_sensitive(false);
405                                 }
406                                 else {
407                                         loopitem->set_sensitive(true);
408                                 }
409                         }
410                 }
411 #endif          
412                 marker_menu_item = item;
413                 marker_menu->popup (1, ev->time);
414         }
415 }
416
417
418 void
419 Editor::new_transport_marker_context_menu (GdkEventButton* ev, ArdourCanvas::Item* item)
420 {
421         if (new_transport_marker_menu == 0) {
422                 build_new_transport_marker_menu ();
423         }
424
425         new_transport_marker_menu->popup (1, ev->time);
426
427 }
428
429 void
430 Editor::transport_marker_context_menu (GdkEventButton* ev, ArdourCanvas::Item* item)
431 {
432         if (transport_marker_menu == 0) {
433                 build_transport_marker_menu ();
434         }
435
436         transport_marker_menu->popup (1, ev->time);
437 }
438
439 void
440 Editor::build_marker_menu ()
441 {
442         using namespace Menu_Helpers;
443
444         marker_menu = new Menu;
445         MenuList& items = marker_menu->items();
446         marker_menu->set_name ("ArdourContextMenu");
447
448         items.push_back (MenuElem (_("Locate to"), mem_fun(*this, &Editor::marker_menu_set_playhead)));
449         items.push_back (MenuElem (_("Play from"), mem_fun(*this, &Editor::marker_menu_play_from)));
450         items.push_back (MenuElem (_("Loop range"), mem_fun(*this, &Editor::marker_menu_loop_range)));
451         items.push_back (MenuElem (_("Set from playhead"), mem_fun(*this, &Editor::marker_menu_set_from_playhead)));
452         items.push_back (MenuElem (_("Set from range"), mem_fun(*this, &Editor::marker_menu_set_from_selection)));
453
454         items.push_back (SeparatorElem());
455
456         items.push_back (MenuElem (_("Rename"), mem_fun(*this, &Editor::marker_menu_rename)));
457         items.push_back (MenuElem (_("Hide"), mem_fun(*this, &Editor::marker_menu_hide)));
458         items.push_back (MenuElem (_("Remove"), mem_fun(*this, &Editor::marker_menu_remove)));
459
460 }
461
462 void
463 Editor::build_range_marker_menu ()
464 {
465         using namespace Menu_Helpers;
466
467         marker_menu = new Menu;
468         MenuList& items = marker_menu->items();
469         marker_menu->set_name ("ArdourContextMenu");
470
471         items.push_back (MenuElem (_("Locate to"), mem_fun(*this, &Editor::marker_menu_set_playhead)));
472         items.push_back (MenuElem (_("Play from"), mem_fun(*this, &Editor::marker_menu_play_from)));
473         items.push_back (MenuElem (_("Loop range"), mem_fun(*this, &Editor::marker_menu_loop_range)));
474         items.push_back (MenuElem (_("Set from playhead"), mem_fun(*this, &Editor::marker_menu_set_from_playhead)));
475         items.push_back (MenuElem (_("Set from range"), mem_fun(*this, &Editor::marker_menu_set_from_selection)));
476
477         items.push_back (SeparatorElem());
478
479         items.push_back (MenuElem (_("Rename"), mem_fun(*this, &Editor::marker_menu_rename)));
480         items.push_back (MenuElem (_("Hide"), mem_fun(*this, &Editor::marker_menu_hide)));
481         items.push_back (MenuElem (_("Remove"), mem_fun(*this, &Editor::marker_menu_remove)));
482
483         items.push_back (SeparatorElem());
484         items.push_back (MenuElem (_("Select all in Range"), mem_fun(*this, &Editor::marker_menu_select_all_selectables_using_range)));
485
486 }
487
488 void
489 Editor::build_tm_marker_menu ()
490 {
491         using namespace Menu_Helpers;
492
493         tm_marker_menu = new Menu;
494         MenuList& items = tm_marker_menu->items();
495         tm_marker_menu->set_name ("ArdourContextMenu");
496
497         items.push_back (MenuElem (_("Edit"), mem_fun(*this, &Editor::marker_menu_edit)));
498         items.push_back (MenuElem (_("Remove"), mem_fun(*this, &Editor::marker_menu_remove)));
499 }
500
501 void
502 Editor::build_new_transport_marker_menu ()
503 {
504         using namespace Menu_Helpers;
505
506         new_transport_marker_menu = new Menu;
507         MenuList& items = new_transport_marker_menu->items();
508         new_transport_marker_menu->set_name ("ArdourContextMenu");
509
510         items.push_back (MenuElem (_("Set Loop Range"), mem_fun(*this, &Editor::new_transport_marker_menu_set_loop)));
511         items.push_back (MenuElem (_("Set Punch Range"), mem_fun(*this, &Editor::new_transport_marker_menu_set_punch)));
512
513         new_transport_marker_menu->signal_unmap_event().connect ( mem_fun(*this, &Editor::new_transport_marker_menu_popdown)); 
514 }
515
516 void
517 Editor::build_transport_marker_menu ()
518 {
519         using namespace Menu_Helpers;
520
521         transport_marker_menu = new Menu;
522         MenuList& items = transport_marker_menu->items();
523         transport_marker_menu->set_name ("ArdourContextMenu");
524
525         items.push_back (MenuElem (_("Locate to"), mem_fun(*this, &Editor::marker_menu_set_playhead)));
526         items.push_back (MenuElem (_("Play from"), mem_fun(*this, &Editor::marker_menu_play_from)));
527         items.push_back (MenuElem (_("Set from playhead"), mem_fun(*this, &Editor::marker_menu_set_from_playhead)));
528         items.push_back (MenuElem (_("Set from range"), mem_fun(*this, &Editor::marker_menu_set_from_selection)));
529         items.push_back (SeparatorElem());
530         items.push_back (MenuElem (_("Hide"), mem_fun(*this, &Editor::marker_menu_hide)));
531         items.push_back (SeparatorElem());
532         items.push_back (MenuElem (_("Select all in Range"), mem_fun(*this, &Editor::marker_menu_select_all_selectables_using_range)));
533 }
534
535 void
536 Editor::marker_menu_hide ()
537 {
538         Marker* marker;
539
540         if ((marker = reinterpret_cast<Marker *> (marker_menu_item->get_data ("marker"))) == 0) {
541                 fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg;
542                 /*NOTREACHED*/
543         }
544
545         Location* l;
546         bool is_start;
547         
548         if ((l = find_location_from_marker (marker, is_start)) != 0) {
549                 l->set_hidden (true, this);
550         }
551 }
552
553 void
554 Editor::marker_menu_select_all_selectables_using_range ()
555 {
556         Marker* marker;
557
558         if ((marker = reinterpret_cast<Marker *> (marker_menu_item->get_data ("marker"))) == 0) {
559                 fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg;
560                 /*NOTREACHED*/
561         }
562
563         Location* l;
564         bool is_start;
565
566         if (((l = find_location_from_marker (marker, is_start)) != 0) && (l->end() > l->start())) {
567                 select_all_within (l->start(), l->end(), 0,  DBL_MAX, Selection::Set);
568         }
569           
570 }
571
572 void
573 Editor::marker_menu_play_from ()
574 {
575         Marker* marker;
576
577         if ((marker = reinterpret_cast<Marker *> (marker_menu_item->get_data ("marker"))) == 0) {
578                 fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg;
579                 /*NOTREACHED*/
580         }
581
582         Location* l;
583         bool is_start;
584         
585         if ((l = find_location_from_marker (marker, is_start)) != 0) {
586
587                 if (l->is_mark()) {
588                         session->request_locate (l->start(), true);
589                 }
590                 else {
591                         //session->request_bounded_roll (l->start(), l->end());
592                         
593                         if (is_start) {
594                                 session->request_locate (l->start(), true);
595                         } else {
596                                 session->request_locate (l->end(), true);
597                         }
598                 }
599         }
600 }
601
602 void
603 Editor::marker_menu_set_playhead ()
604 {
605         Marker* marker;
606
607         if ((marker = reinterpret_cast<Marker *> (marker_menu_item->get_data ("marker"))) == 0) {
608                 fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg;
609                 /*NOTREACHED*/
610         }
611
612         Location* l;
613         bool is_start;
614         
615         if ((l = find_location_from_marker (marker, is_start)) != 0) {
616
617                 if (l->is_mark()) {
618                         session->request_locate (l->start(), false);
619                 }
620                 else {
621                         if (is_start) {
622                                 session->request_locate (l->start(), false);
623                         } else {
624                                 session->request_locate (l->end(), false);
625                         }
626                 }
627         }
628 }
629
630 void
631 Editor::marker_menu_set_from_playhead ()
632 {
633         Marker* marker;
634
635         if ((marker = reinterpret_cast<Marker *> (marker_menu_item->get_data ("marker"))) == 0) {
636                 fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg;
637                 /*NOTREACHED*/
638         }
639
640         Location* l;
641         bool is_start;
642         
643         if ((l = find_location_from_marker (marker, is_start)) != 0) {
644
645                 if (l->is_mark()) {
646                         l->set_start (session->transport_frame ());
647                 }
648                 else {
649                         if (is_start) {
650                                 l->set_start (session->transport_frame ());
651                         } else {
652                                 l->set_end (session->transport_frame ());
653                         }
654                 }
655         }
656 }
657
658 void
659 Editor::marker_menu_set_from_selection ()
660 {
661         Marker* marker;
662
663         if ((marker = reinterpret_cast<Marker *> (marker_menu_item->get_data ("marker"))) == 0) {
664                 fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg;
665                 /*NOTREACHED*/
666         }
667
668         Location* l;
669         bool is_start;
670         
671         if ((l = find_location_from_marker (marker, is_start)) != 0) {
672
673                 if (l->is_mark()) {
674                         // nothing for now
675                 }
676                 else {
677
678                         /* if range selection use first to last */
679
680                         if (mouse_mode == Editing::MouseRange) {
681                                 if (!selection->time.empty()) {
682                                         l->set_start (selection->time.start());
683                                         l->set_end (selection->time.end_frame());
684                                 }
685                         }
686                         else {
687                                 if (!selection->audio_regions.empty()) {
688                                         l->set_start (selection->audio_regions.start());
689                                         l->set_end (selection->audio_regions.end_frame());
690                                 }
691                         }
692                 }
693         }
694 }
695
696 void
697 Editor::marker_menu_loop_range ()
698 {
699         Marker* marker;
700
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;
703                 /*NOTREACHED*/
704         }
705
706         Location* l;
707         bool is_start;
708         
709         if ((l = find_location_from_marker (marker, is_start)) != 0) {
710                 Location* l2;
711                 if ((l2 = transport_loop_location()) != 0) {
712                         l2->set (l->start(), l->end());
713                         
714                         // enable looping, reposition and start rolling
715                         session->request_auto_loop(true);
716                         session->request_locate (l2->start(), true);
717                 }
718         }
719 }
720
721 void
722 Editor::marker_menu_edit ()
723 {
724         MeterMarker* mm;
725         TempoMarker* tm;
726         Marker* marker;
727
728         if ((marker = reinterpret_cast<Marker *> (marker_menu_item->get_data ("marker"))) == 0) {
729                 fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg;
730                 /*NOTREACHED*/
731         }
732
733         if ((mm = dynamic_cast<MeterMarker*> (marker)) != 0) {
734                 edit_meter_section (&mm->meter());
735         } else if ((tm = dynamic_cast<TempoMarker*> (marker)) != 0) {
736                 edit_tempo_section (&tm->tempo());
737         } else {
738                 fatal << X_("programming erorr: unhandled marker type in Editor::marker_menu_edit")
739                       << endmsg;
740                 /*NOTREACHED*/
741         }
742 }
743
744 void
745 Editor::marker_menu_remove ()
746 {
747         MeterMarker* mm;
748         TempoMarker* tm;
749         Marker* marker;
750
751         if ((marker = reinterpret_cast<Marker *> (marker_menu_item->get_data ("marker"))) == 0) {
752                 fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg;
753                 /*NOTREACHED*/
754         }
755
756         if ((mm = dynamic_cast<MeterMarker*> (marker)) != 0) {
757                 remove_meter_marker (marker_menu_item);
758         } else if ((tm = dynamic_cast<TempoMarker*> (marker)) != 0) {
759                 remove_tempo_marker (marker_menu_item);
760         } else {
761                 remove_marker (*marker_menu_item, (GdkEvent*) 0);
762         }
763 }
764
765 void
766 Editor::marker_menu_rename ()
767 {
768         Marker* marker;
769
770         if ((marker = reinterpret_cast<Marker *> (marker_menu_item->get_data ("marker"))) == 0) {
771                 fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg;
772                 /*NOTREACHED*/
773         }
774
775         Location* loc;
776         bool is_start;
777
778         loc = find_location_from_marker (marker, is_start);
779
780         if (!loc) return;
781         
782         Dialog dialog;
783         Entry  entry;
784         
785         if (loc->is_mark()) {
786                 dialog.set_title (_("ardour: rename mark"));
787         } else {
788                 dialog.set_title (_("ardour: rename range"));
789         }
790
791         dialog.set_name ("MarkRenameWindow");
792         dialog.set_size_request (300, -1);
793         dialog.set_position (Gtk::WIN_POS_MOUSE);
794         dialog.set_modal (true);
795
796         dialog.add_action_widget (entry, RESPONSE_ACCEPT);
797         dialog.add_button (Stock::OK, RESPONSE_ACCEPT);
798         dialog.add_button (Stock::CANCEL, RESPONSE_ACCEPT);
799
800         entry.set_text (loc->name());
801         entry.set_name ("MarkerNameDisplay");
802
803         dialog.show_all ();
804         entry.grab_focus ();
805
806         switch (dialog.run ()) {
807         case RESPONSE_ACCEPT:
808                 break;
809         default:
810                 return;
811         }
812
813         begin_reversible_command ( _("rename marker") );
814         session->add_undo( session->locations()->get_memento() );
815
816         loc->set_name (entry.get_text());
817         
818         session->add_redo_no_execute( session->locations()->get_memento() );
819         commit_reversible_command ();
820 }
821
822 gint
823 Editor::new_transport_marker_menu_popdown (GdkEventAny *ev)
824 {
825         // hide rects
826         transport_bar_drag_rect->hide();
827         range_marker_drag_rect->hide();
828
829         return FALSE;
830 }
831
832 void
833 Editor::new_transport_marker_menu_set_loop ()
834 {
835         if (!session) return;
836         
837         begin_reversible_command (_("set loop range"));
838         
839         Location* tll;
840
841         if ((tll = transport_loop_location()) == 0) {
842                 Location* loc = new Location (temp_location->start(), temp_location->end(), _("Loop"),  Location::IsAutoLoop);
843                 session->add_undo (session->locations()->get_memento());
844                 session->locations()->add (loc, true);
845                 session->set_auto_loop_location (loc);
846                 session->add_redo_no_execute (session->locations()->get_memento());
847         }
848         else {
849                 session->add_undo (retype_return<void>(bind (mem_fun (*tll, &Location::set), tll->start(), tll->end())));
850                 session->add_redo (retype_return<void>(bind (mem_fun (*tll, &Location::set), temp_location->start(), temp_location->end())));
851                 tll->set_hidden (false, this);
852                 tll->set (temp_location->start(), temp_location->end());
853         }
854         
855         commit_reversible_command ();
856 }
857
858 void
859 Editor::new_transport_marker_menu_set_punch ()
860 {
861         if (!session) return;
862         
863         begin_reversible_command (_("set punch range"));
864         
865         Location* tpl;
866
867         if ((tpl = transport_punch_location()) == 0) {
868                 tpl = new Location (temp_location->start(), temp_location->end(), _("Punch"), Location::IsAutoPunch);
869                 session->add_undo (session->locations()->get_memento());
870                 session->locations()->add (tpl, true);
871                 session->set_auto_punch_location (tpl);
872                 session->add_redo_no_execute (session->locations()->get_memento());
873         } else {
874                 session->add_undo (retype_return<void>(bind (mem_fun (*tpl, &Location::set), tpl->start(), tpl->end())));
875                 session->add_redo (retype_return<void>(bind (mem_fun (*tpl, &Location::set), temp_location->start(), temp_location->end())));
876                 tpl->set_hidden(false, this);
877                 tpl->set(temp_location->start(), temp_location->end());
878         }
879         
880         commit_reversible_command ();
881 }
882
883 void
884 Editor::update_loop_range_view (bool visibility)
885 {
886         if (session == 0) {
887                 return;
888         }
889
890         Location* tll;
891
892         if (session->get_auto_loop() && ((tll = transport_loop_location()) != 0)) {
893
894                 double x1 = frame_to_pixel (tll->start());
895                 double x2 = frame_to_pixel (tll->end());
896                 
897                 transport_loop_range_rect->property_x1() = x1;
898                 transport_loop_range_rect->property_x2() = x2;
899                 
900                 if (visibility) {
901                         transport_loop_range_rect->show();
902                 }
903         }
904         else if (visibility) {
905                 transport_loop_range_rect->hide();
906         }
907 }
908
909 void
910 Editor::update_punch_range_view (bool visibility)
911 {
912         if (session == 0) {
913                 return;
914         }
915
916         Location* tpl;
917
918         if ((session->get_punch_in() || session->get_punch_out()) && ((tpl = transport_punch_location()) != 0)) {
919
920                 double x1 = frame_to_pixel (tpl->start());
921                 double x2 = frame_to_pixel (tpl->end());
922                 
923                 transport_punch_range_rect->property_x1() = x1;
924                 transport_punch_range_rect->property_x2() = x2;
925                 
926                 if (visibility) {
927                         transport_punch_range_rect->show();
928                 }
929         }
930         else if (visibility) {
931                 transport_punch_range_rect->hide();
932         }
933
934 //      if (session->get_punch_in()) {
935 //              double x = frame_to_pixel (transport_punch_location->start());
936 //              gnome_canvas_item_set (transport_punchin_line, "x1", x, "x2", x, NULL);
937                 
938 //              if (visibility) {
939 //                      gnome_canvas_item_show (transport_punchin_line);
940 //              }
941 //      }
942 //      else if (visibility) {
943 //              gnome_canvas_item_hide (transport_punchin_line);
944 //      }
945         
946 //      if (session->get_punch_out()) {
947 //              double x = frame_to_pixel (transport_punch_location->end());
948                 
949 //              gnome_canvas_item_set (transport_punchout_line, "x1", x, "x2", x, NULL);
950                 
951 //              if (visibility) {
952 //                      gnome_canvas_item_show (transport_punchout_line);
953 //              }
954 //      }
955 //      else if (visibility) {
956 //              gnome_canvas_item_hide (transport_punchout_line);
957 //      }
958 }