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