fix incorrect marker/range marker right-click menus, try to clarify the text in them...
[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 void
372 Editor::marker_context_menu (GdkEventButton* ev, ArdourCanvas::Item* item)
373 {
374         Marker * marker;
375         if ((marker = reinterpret_cast<Marker *> (item->get_data("marker"))) == 0) {
376                 fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg;
377                 /*NOTREACHED*/
378         }
379         
380         bool is_start;
381         Location * loc = find_location_from_marker (marker, is_start);
382         if (loc == transport_loop_location() || loc == transport_punch_location()) {
383                 if (transport_marker_menu == 0) {
384                         build_transport_marker_menu ();
385                 }
386                 marker_menu_item = item;
387                 transport_marker_menu->popup (1, ev->time);
388         } else {
389
390                 if (loc->is_mark()) {
391                        if (marker_menu == 0) {
392                               build_marker_menu ();
393                        }
394
395
396                 // GTK2FIX use action group sensitivity
397 #ifdef GTK2FIX
398                 if (children.size() >= 3) {
399                         MenuItem * loopitem = &children[2];
400                         if (loopitem) {
401                                 if (loc->is_mark()) {
402                                         loopitem->set_sensitive(false);
403                                 }
404                                 else {
405                                         loopitem->set_sensitive(true);
406                                 }
407                         }
408                 }
409 #endif          
410                 marker_menu_item = item;
411                 marker_menu->popup (1, ev->time);
412                 }
413
414                 if (loc->is_range_marker()) {
415                        if (range_marker_menu == 0){
416                               build_range_marker_menu ();
417                        }
418                        marker_menu_item = item;
419                        range_marker_menu->popup (1, ev->time);
420                 }
421         }
422 }
423
424 void
425 Editor::new_transport_marker_context_menu (GdkEventButton* ev, ArdourCanvas::Item* item)
426 {
427         if (new_transport_marker_menu == 0) {
428                 build_new_transport_marker_menu ();
429         }
430
431         new_transport_marker_menu->popup (1, ev->time);
432
433 }
434
435 void
436 Editor::transport_marker_context_menu (GdkEventButton* ev, ArdourCanvas::Item* item)
437 {
438         if (transport_marker_menu == 0) {
439                 build_transport_marker_menu ();
440         }
441
442         transport_marker_menu->popup (1, ev->time);
443 }
444
445 void
446 Editor::build_marker_menu ()
447 {
448         using namespace Menu_Helpers;
449
450         marker_menu = new Menu;
451         MenuList& items = marker_menu->items();
452         marker_menu->set_name ("ArdourContextMenu");
453
454         items.push_back (MenuElem (_("Locate to mark"), mem_fun(*this, &Editor::marker_menu_set_playhead)));
455         items.push_back (MenuElem (_("Play from mark"), mem_fun(*this, &Editor::marker_menu_play_from)));
456         items.push_back (MenuElem (_("Set mark from playhead"), mem_fun(*this, &Editor::marker_menu_set_from_playhead)));
457
458         items.push_back (SeparatorElem());
459
460         items.push_back (MenuElem (_("Rename"), mem_fun(*this, &Editor::marker_menu_rename)));
461         items.push_back (MenuElem (_("Hide"), mem_fun(*this, &Editor::marker_menu_hide)));
462         items.push_back (MenuElem (_("Remove"), mem_fun(*this, &Editor::marker_menu_remove)));
463
464 }
465
466 void
467 Editor::build_range_marker_menu ()
468 {
469         using namespace Menu_Helpers;
470
471         range_marker_menu = new Menu;
472         MenuList& items = range_marker_menu->items();
473         range_marker_menu->set_name ("ArdourContextMenu");
474
475         items.push_back (MenuElem (_("Locate to range mark"), mem_fun(*this, &Editor::marker_menu_set_playhead)));
476         items.push_back (MenuElem (_("Play from range mark"), mem_fun(*this, &Editor::marker_menu_play_from)));
477         items.push_back (MenuElem (_("Loop range"), mem_fun(*this, &Editor::marker_menu_loop_range)));
478         items.push_back (MenuElem (_("Set range mark from playhead"), mem_fun(*this, &Editor::marker_menu_set_from_playhead)));
479         items.push_back (MenuElem (_("Set range from range selection"), mem_fun(*this, &Editor::marker_menu_set_from_selection)));
480
481         items.push_back (SeparatorElem());
482
483         items.push_back (MenuElem (_("Rename range"), mem_fun(*this, &Editor::marker_menu_rename)));
484         items.push_back (MenuElem (_("Hide range"), mem_fun(*this, &Editor::marker_menu_hide)));
485         items.push_back (MenuElem (_("Remove range"), mem_fun(*this, &Editor::marker_menu_remove)));
486
487         items.push_back (SeparatorElem());
488
489         items.push_back (MenuElem (_("Separate regions from range"), mem_fun(*this, &Editor::marker_menu_separate_regions_using_location)));
490         items.push_back (MenuElem (_("Select all in range"), mem_fun(*this, &Editor::marker_menu_select_all_selectables_using_range)));
491
492 }
493
494 void
495 Editor::build_tm_marker_menu ()
496 {
497         using namespace Menu_Helpers;
498
499         tm_marker_menu = new Menu;
500         MenuList& items = tm_marker_menu->items();
501         tm_marker_menu->set_name ("ArdourContextMenu");
502
503         items.push_back (MenuElem (_("Edit"), mem_fun(*this, &Editor::marker_menu_edit)));
504         items.push_back (MenuElem (_("Remove"), mem_fun(*this, &Editor::marker_menu_remove)));
505 }
506
507 void
508 Editor::build_new_transport_marker_menu ()
509 {
510         using namespace Menu_Helpers;
511
512         new_transport_marker_menu = new Menu;
513         MenuList& items = new_transport_marker_menu->items();
514         new_transport_marker_menu->set_name ("ArdourContextMenu");
515
516         items.push_back (MenuElem (_("Set Loop Range"), mem_fun(*this, &Editor::new_transport_marker_menu_set_loop)));
517         items.push_back (MenuElem (_("Set Punch Range"), mem_fun(*this, &Editor::new_transport_marker_menu_set_punch)));
518
519         new_transport_marker_menu->signal_unmap_event().connect ( mem_fun(*this, &Editor::new_transport_marker_menu_popdown)); 
520 }
521
522 void
523 Editor::build_transport_marker_menu ()
524 {
525         using namespace Menu_Helpers;
526
527         transport_marker_menu = new Menu;
528         MenuList& items = transport_marker_menu->items();
529         transport_marker_menu->set_name ("ArdourContextMenu");
530
531         items.push_back (MenuElem (_("Locate to"), mem_fun(*this, &Editor::marker_menu_set_playhead)));
532         items.push_back (MenuElem (_("Play from"), mem_fun(*this, &Editor::marker_menu_play_from)));
533         items.push_back (MenuElem (_("Set from playhead"), mem_fun(*this, &Editor::marker_menu_set_from_playhead)));
534         items.push_back (MenuElem (_("Set from range"), mem_fun(*this, &Editor::marker_menu_set_from_selection)));
535         items.push_back (SeparatorElem());
536         items.push_back (MenuElem (_("Hide"), mem_fun(*this, &Editor::marker_menu_hide)));
537         items.push_back (SeparatorElem());
538         items.push_back (MenuElem (_("Select all in Range"), mem_fun(*this, &Editor::marker_menu_select_all_selectables_using_range)));
539 }
540
541 void
542 Editor::marker_menu_hide ()
543 {
544         Marker* marker;
545
546         if ((marker = reinterpret_cast<Marker *> (marker_menu_item->get_data ("marker"))) == 0) {
547                 fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg;
548                 /*NOTREACHED*/
549         }
550
551         Location* l;
552         bool is_start;
553         
554         if ((l = find_location_from_marker (marker, is_start)) != 0) {
555                 l->set_hidden (true, this);
556         }
557 }
558
559 void
560 Editor::marker_menu_select_all_selectables_using_range ()
561 {
562         Marker* marker;
563
564         if ((marker = reinterpret_cast<Marker *> (marker_menu_item->get_data ("marker"))) == 0) {
565                 fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg;
566                 /*NOTREACHED*/
567         }
568
569         Location* l;
570         bool is_start;
571
572         if (((l = find_location_from_marker (marker, is_start)) != 0) && (l->end() > l->start())) {
573                 select_all_within (l->start(), l->end() - 1, 0,  DBL_MAX, Selection::Set);
574         }
575           
576 }
577
578 void
579 Editor::marker_menu_separate_regions_using_location ()
580 {
581         Marker* marker;
582
583         if ((marker = reinterpret_cast<Marker *> (marker_menu_item->get_data ("marker"))) == 0) {
584                 fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg;
585                 /*NOTREACHED*/
586         }
587
588         Location* l;
589         bool is_start;
590
591         if (((l = find_location_from_marker (marker, is_start)) != 0) && (l->end() > l->start())) {
592                 separate_regions_using_location (*l);
593         }
594           
595 }
596
597 void
598 Editor::marker_menu_play_from ()
599 {
600         Marker* marker;
601
602         if ((marker = reinterpret_cast<Marker *> (marker_menu_item->get_data ("marker"))) == 0) {
603                 fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg;
604                 /*NOTREACHED*/
605         }
606
607         Location* l;
608         bool is_start;
609         
610         if ((l = find_location_from_marker (marker, is_start)) != 0) {
611
612                 if (l->is_mark()) {
613                         session->request_locate (l->start(), true);
614                 }
615                 else {
616                         //session->request_bounded_roll (l->start(), l->end());
617                         
618                         if (is_start) {
619                                 session->request_locate (l->start(), true);
620                         } else {
621                                 session->request_locate (l->end(), true);
622                         }
623                 }
624         }
625 }
626
627 void
628 Editor::marker_menu_set_playhead ()
629 {
630         Marker* marker;
631
632         if ((marker = reinterpret_cast<Marker *> (marker_menu_item->get_data ("marker"))) == 0) {
633                 fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg;
634                 /*NOTREACHED*/
635         }
636
637         Location* l;
638         bool is_start;
639         
640         if ((l = find_location_from_marker (marker, is_start)) != 0) {
641
642                 if (l->is_mark()) {
643                         session->request_locate (l->start(), false);
644                 }
645                 else {
646                         if (is_start) {
647                                 session->request_locate (l->start(), false);
648                         } else {
649                                 session->request_locate (l->end(), false);
650                         }
651                 }
652         }
653 }
654
655 void
656 Editor::marker_menu_set_from_playhead ()
657 {
658         Marker* marker;
659
660         if ((marker = reinterpret_cast<Marker *> (marker_menu_item->get_data ("marker"))) == 0) {
661                 fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg;
662                 /*NOTREACHED*/
663         }
664
665         Location* l;
666         bool is_start;
667         
668         if ((l = find_location_from_marker (marker, is_start)) != 0) {
669
670                 if (l->is_mark()) {
671                         l->set_start (session->transport_frame ());
672                 }
673                 else {
674                         if (is_start) {
675                                 l->set_start (session->transport_frame ());
676                         } else {
677                                 l->set_end (session->transport_frame ());
678                         }
679                 }
680         }
681 }
682
683 void
684 Editor::marker_menu_set_from_selection ()
685 {
686         Marker* marker;
687
688         if ((marker = reinterpret_cast<Marker *> (marker_menu_item->get_data ("marker"))) == 0) {
689                 fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg;
690                 /*NOTREACHED*/
691         }
692
693         Location* l;
694         bool is_start;
695         
696         if ((l = find_location_from_marker (marker, is_start)) != 0) {
697
698                 if (l->is_mark()) {
699                         // nothing for now
700                 }
701                 else {
702
703                         /* if range selection use first to last */
704
705                         if (mouse_mode == Editing::MouseRange) {
706                                 if (!selection->time.empty()) {
707                                         l->set_start (selection->time.start());
708                                         l->set_end (selection->time.end_frame());
709                                 }
710                         }
711                         else {
712                                 if (!selection->audio_regions.empty()) {
713                                         l->set_start (selection->audio_regions.start());
714                                         l->set_end (selection->audio_regions.end_frame());
715                                 }
716                         }
717                 }
718         }
719 }
720
721 void
722 Editor::marker_menu_loop_range ()
723 {
724         Marker* marker;
725
726         if ((marker = reinterpret_cast<Marker *> (marker_menu_item->get_data ("marker"))) == 0) {
727                 fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg;
728                 /*NOTREACHED*/
729         }
730
731         Location* l;
732         bool is_start;
733         
734         if ((l = find_location_from_marker (marker, is_start)) != 0) {
735                 Location* l2;
736                 if ((l2 = transport_loop_location()) != 0) {
737                         l2->set (l->start(), l->end());
738                         
739                         // enable looping, reposition and start rolling
740                         session->request_auto_loop(true);
741                         session->request_locate (l2->start(), true);
742                 }
743         }
744 }
745
746 void
747 Editor::marker_menu_edit ()
748 {
749         MeterMarker* mm;
750         TempoMarker* tm;
751         Marker* marker;
752
753         if ((marker = reinterpret_cast<Marker *> (marker_menu_item->get_data ("marker"))) == 0) {
754                 fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg;
755                 /*NOTREACHED*/
756         }
757
758         if ((mm = dynamic_cast<MeterMarker*> (marker)) != 0) {
759                 edit_meter_section (&mm->meter());
760         } else if ((tm = dynamic_cast<TempoMarker*> (marker)) != 0) {
761                 edit_tempo_section (&tm->tempo());
762         } else {
763                 fatal << X_("programming erorr: unhandled marker type in Editor::marker_menu_edit")
764                       << endmsg;
765                 /*NOTREACHED*/
766         }
767 }
768
769 void
770 Editor::marker_menu_remove ()
771 {
772         MeterMarker* mm;
773         TempoMarker* tm;
774         Marker* marker;
775
776         if ((marker = reinterpret_cast<Marker *> (marker_menu_item->get_data ("marker"))) == 0) {
777                 fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg;
778                 /*NOTREACHED*/
779         }
780
781         if ((mm = dynamic_cast<MeterMarker*> (marker)) != 0) {
782                 remove_meter_marker (marker_menu_item);
783         } else if ((tm = dynamic_cast<TempoMarker*> (marker)) != 0) {
784                 remove_tempo_marker (marker_menu_item);
785         } else {
786                 remove_marker (*marker_menu_item, (GdkEvent*) 0);
787         }
788 }
789
790 void
791 Editor::marker_menu_rename ()
792 {
793         Marker* marker;
794
795         if ((marker = reinterpret_cast<Marker *> (marker_menu_item->get_data ("marker"))) == 0) {
796                 fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg;
797                 /*NOTREACHED*/
798         }
799
800         Location* loc;
801         bool is_start;
802
803         loc = find_location_from_marker (marker, is_start);
804
805         if (!loc) return;
806         
807         Dialog dialog;
808         Entry  entry;
809         
810         if (loc->is_mark()) {
811                 dialog.set_title (_("ardour: rename mark"));
812         } else {
813                 dialog.set_title (_("ardour: rename range"));
814         }
815
816         dialog.set_name ("MarkRenameWindow");
817         dialog.set_size_request (300, -1);
818         dialog.set_position (Gtk::WIN_POS_MOUSE);
819         dialog.set_modal (true);
820
821         dialog.add_action_widget (entry, RESPONSE_ACCEPT);
822         dialog.add_button (Stock::OK, RESPONSE_ACCEPT);
823         dialog.add_button (Stock::CANCEL, RESPONSE_ACCEPT);
824
825         entry.set_text (loc->name());
826         entry.set_name ("MarkerNameDisplay");
827
828         dialog.show_all ();
829         entry.grab_focus ();
830
831         switch (dialog.run ()) {
832         case RESPONSE_ACCEPT:
833                 break;
834         default:
835                 return;
836         }
837
838         begin_reversible_command ( _("rename marker") );
839         session->add_undo( session->locations()->get_memento() );
840
841         loc->set_name (entry.get_text());
842         
843         session->add_redo_no_execute( session->locations()->get_memento() );
844         commit_reversible_command ();
845 }
846
847 gint
848 Editor::new_transport_marker_menu_popdown (GdkEventAny *ev)
849 {
850         // hide rects
851         transport_bar_drag_rect->hide();
852         range_marker_drag_rect->hide();
853
854         return FALSE;
855 }
856
857 void
858 Editor::new_transport_marker_menu_set_loop ()
859 {
860         if (!session) return;
861         
862         begin_reversible_command (_("set loop range"));
863         
864         Location* tll;
865
866         if ((tll = transport_loop_location()) == 0) {
867                 Location* loc = new Location (temp_location->start(), temp_location->end(), _("Loop"),  Location::IsAutoLoop);
868                 session->add_undo (session->locations()->get_memento());
869                 session->locations()->add (loc, true);
870                 session->set_auto_loop_location (loc);
871                 session->add_redo_no_execute (session->locations()->get_memento());
872         }
873         else {
874                 session->add_undo (retype_return<void>(bind (mem_fun (*tll, &Location::set), tll->start(), tll->end())));
875                 session->add_redo (retype_return<void>(bind (mem_fun (*tll, &Location::set), temp_location->start(), temp_location->end())));
876                 tll->set_hidden (false, this);
877                 tll->set (temp_location->start(), temp_location->end());
878         }
879         
880         commit_reversible_command ();
881 }
882
883 void
884 Editor::new_transport_marker_menu_set_punch ()
885 {
886         if (!session) return;
887         
888         begin_reversible_command (_("set punch range"));
889         
890         Location* tpl;
891
892         if ((tpl = transport_punch_location()) == 0) {
893                 tpl = new Location (temp_location->start(), temp_location->end(), _("Punch"), Location::IsAutoPunch);
894                 session->add_undo (session->locations()->get_memento());
895                 session->locations()->add (tpl, true);
896                 session->set_auto_punch_location (tpl);
897                 session->add_redo_no_execute (session->locations()->get_memento());
898         } else {
899                 session->add_undo (retype_return<void>(bind (mem_fun (*tpl, &Location::set), tpl->start(), tpl->end())));
900                 session->add_redo (retype_return<void>(bind (mem_fun (*tpl, &Location::set), temp_location->start(), temp_location->end())));
901                 tpl->set_hidden(false, this);
902                 tpl->set(temp_location->start(), temp_location->end());
903         }
904         
905         commit_reversible_command ();
906 }
907
908 void
909 Editor::update_loop_range_view (bool visibility)
910 {
911         if (session == 0) {
912                 return;
913         }
914
915         Location* tll;
916
917         if (session->get_auto_loop() && ((tll = transport_loop_location()) != 0)) {
918
919                 double x1 = frame_to_pixel (tll->start());
920                 double x2 = frame_to_pixel (tll->end());
921                 
922                 transport_loop_range_rect->property_x1() = x1;
923                 transport_loop_range_rect->property_x2() = x2;
924                 
925                 if (visibility) {
926                         transport_loop_range_rect->show();
927                 }
928         }
929         else if (visibility) {
930                 transport_loop_range_rect->hide();
931         }
932 }
933
934 void
935 Editor::update_punch_range_view (bool visibility)
936 {
937         if (session == 0) {
938                 return;
939         }
940
941         Location* tpl;
942
943         if ((session->get_punch_in() || session->get_punch_out()) && ((tpl = transport_punch_location()) != 0)) {
944
945                 double x1 = frame_to_pixel (tpl->start());
946                 double x2 = frame_to_pixel (tpl->end());
947                 
948                 transport_punch_range_rect->property_x1() = x1;
949                 transport_punch_range_rect->property_x2() = x2;
950                 
951                 if (visibility) {
952                         transport_punch_range_rect->show();
953                 }
954         }
955         else if (visibility) {
956                 transport_punch_range_rect->hide();
957         }
958
959 //      if (session->get_punch_in()) {
960 //              double x = frame_to_pixel (transport_punch_location->start());
961 //              gnome_canvas_item_set (transport_punchin_line, "x1", x, "x2", x, NULL);
962                 
963 //              if (visibility) {
964 //                      gnome_canvas_item_show (transport_punchin_line);
965 //              }
966 //      }
967 //      else if (visibility) {
968 //              gnome_canvas_item_hide (transport_punchin_line);
969 //      }
970         
971 //      if (session->get_punch_out()) {
972 //              double x = frame_to_pixel (transport_punch_location->end());
973                 
974 //              gnome_canvas_item_set (transport_punchout_line, "x1", x, "x2", x, NULL);
975                 
976 //              if (visibility) {
977 //                      gnome_canvas_item_show (transport_punchout_line);
978 //              }
979 //      }
980 //      else if (visibility) {
981 //              gnome_canvas_item_hide (transport_punchout_line);
982 //      }
983 }