use AudioClock::set_widget_name() for rec status in big clock, not set_name(), to...
[ardour.git] / gtk2_ardour / ardour_ui.cc
1 /*
2     Copyright (C) 1999-2002 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 <algorithm>
22 #include <cmath>
23 #include <fcntl.h>
24 #include <signal.h>
25 #include <unistd.h>
26 #include <cerrno>
27 #include <fstream>
28
29 #include <iostream>
30
31 #include <gtkmm/messagedialog.h>
32 #include <gtkmm/accelmap.h>
33
34 #include <pbd/error.h>
35 #include <pbd/compose.h>
36 #include <pbd/pathscanner.h>
37 #include <pbd/failed_constructor.h>
38 #include <pbd/enumwriter.h>
39 #include <gtkmm2ext/gtk_ui.h>
40 #include <gtkmm2ext/utils.h>
41 #include <gtkmm2ext/click_box.h>
42 #include <gtkmm2ext/fastmeter.h>
43 #include <gtkmm2ext/stop_signal.h>
44 #include <gtkmm2ext/popup.h>
45
46 #include <midi++/port.h>
47 #include <midi++/mmc.h>
48
49 #include <ardour/ardour.h>
50 #include <ardour/session_route.h>
51 #include <ardour/port.h>
52 #include <ardour/audioengine.h>
53 #include <ardour/playlist.h>
54 #include <ardour/utils.h>
55 #include <ardour/audio_diskstream.h>
56 #include <ardour/audiofilesource.h>
57 #include <ardour/recent_sessions.h>
58 #include <ardour/port.h>
59 #include <ardour/audio_track.h>
60
61 #include "actions.h"
62 #include "ardour_ui.h"
63 #include "public_editor.h"
64 #include "audio_clock.h"
65 #include "keyboard.h"
66 #include "mixer_ui.h"
67 #include "prompter.h"
68 #include "opts.h"
69 #include "keyboard_target.h"
70 #include "add_route_dialog.h"
71 #include "new_session_dialog.h"
72 #include "about.h"
73 #include "utils.h"
74 #include "gui_thread.h"
75 #include "color_manager.h"
76
77 #include "i18n.h"
78
79 using namespace ARDOUR;
80 using namespace PBD;
81 using namespace Gtkmm2ext;
82 using namespace Gtk;
83 using namespace sigc;
84
85 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
86
87 sigc::signal<void,bool> ARDOUR_UI::Blink;
88 sigc::signal<void>      ARDOUR_UI::RapidScreenUpdate;
89 sigc::signal<void>      ARDOUR_UI::SuperRapidScreenUpdate;
90 sigc::signal<void,nframes_t> ARDOUR_UI::Clock;
91
92 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], string rcfile)
93
94         : Gtkmm2ext::UI ("ardour", argcp, argvp, rcfile),
95           
96           primary_clock (X_("primary"), false, X_("TransportClockDisplay"), true, false, true),
97           secondary_clock (X_("secondary"), false, X_("SecondaryClockDisplay"), true, false, true),
98           preroll_clock (X_("preroll"), false, X_("PreRollClock"), true, true),
99           postroll_clock (X_("postroll"), false, X_("PostRollClock"), true, true),
100
101           /* adjuster table */
102
103           adjuster_table (3, 3),
104
105           /* preroll stuff */
106
107           preroll_button (_("pre\nroll")),
108           postroll_button (_("post\nroll")),
109
110           /* big clock */
111
112           big_clock (X_("bigclock"), false, "BigClockNonRecording", true, false, true),
113
114           /* transport */
115
116           time_master_button (_("time\nmaster")),
117
118           shuttle_units_button (_("% ")),
119
120           punch_in_button (_("Punch In")),
121           punch_out_button (_("Punch Out")),
122           auto_return_button (_("Auto Return")),
123           auto_play_button (_("Autuo Play")),
124           auto_input_button (_("Auto Input")),
125           click_button (_("Click")),
126           auditioning_alert_button (_("AUDITION")),
127           solo_alert_button (_("SOLO")),
128           shown_flag (false)
129 {
130         using namespace Gtk::Menu_Helpers;
131
132         Gtkmm2ext::init();
133         
134         about = 0;
135
136         if (theArdourUI == 0) {
137                 theArdourUI = this;
138         }
139
140         /* load colors */
141
142         color_manager = new ColorManager();
143
144         std::string color_file = ARDOUR::find_config_file("ardour.colors");
145
146         color_manager->load (color_file);
147
148         editor = 0;
149         mixer = 0;
150         session = 0;
151         _session_is_new = false;
152         big_clock_window = 0;
153         session_selector_window = 0;
154         last_key_press_time = 0;
155         connection_editor = 0;
156         add_route_dialog = 0;
157         route_params = 0;
158         option_editor = 0;
159         location_ui = 0;
160         open_session_selector = 0;
161         have_configure_timeout = false;
162         have_disk_overrun_displayed = false;
163         have_disk_underrun_displayed = false;
164         _will_create_new_session_automatically = false;
165         session_loaded = false;
166         last_speed_displayed = -1.0f;
167         keybindings_path = ARDOUR::find_config_file ("ardour.bindings");
168
169         can_save_keybindings = false;
170         Glib::signal_idle().connect (mem_fun (*this, &ARDOUR_UI::first_idle));
171
172         last_configure_time.tv_sec = 0;
173         last_configure_time.tv_usec = 0;
174
175         shuttle_grabbed = false;
176         shuttle_fract = 0.0;
177         shuttle_max_speed = 8.0f;
178
179         shuttle_style_menu = 0;
180         shuttle_unit_menu = 0;
181
182         gettimeofday (&last_peak_grab, 0);
183         gettimeofday (&last_shuttle_request, 0);
184
185         ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
186         ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
187
188         /* handle pending state with a dialog */
189
190         ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
191
192         /* have to wait for AudioEngine and Configuration before proceeding */
193 }
194
195 void
196 ARDOUR_UI::set_engine (AudioEngine& e)
197 {
198         engine = &e;
199
200         engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
201         engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
202         engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
203         engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
204
205         ActionManager::init ();
206         new_session_dialog = new NewSessionDialog();
207
208         _tooltips.enable();
209
210         keyboard = new Keyboard;
211
212         if (setup_windows ()) {
213                 throw failed_constructor ();
214         }
215
216         if (GTK_ARDOUR::show_key_actions) {
217                 vector<string> names;
218                 vector<string> paths;
219                 vector<string> keys;
220                 vector<AccelKey> bindings;
221
222                 ActionManager::get_all_actions (names, paths, keys, bindings);
223
224                 vector<string>::iterator n;
225                 vector<string>::iterator k;
226                 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
227                         cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
228                 }
229
230                 exit (0);
231         }
232
233         /* start with timecode, metering enabled
234         */
235         
236         blink_timeout_tag = -1;
237
238         /* the global configuration object is now valid */
239
240         use_config ();
241
242         /* this being a GUI and all, we want peakfiles */
243
244         AudioFileSource::set_build_peakfiles (true);
245         AudioFileSource::set_build_missing_peakfiles (true);
246
247         if (AudioSource::start_peak_thread ()) {
248                 throw failed_constructor();
249         }
250
251         /* set default clock modes */
252
253         primary_clock.set_mode (AudioClock::SMPTE);
254         secondary_clock.set_mode (AudioClock::BBT);
255
256         /* start the time-of-day-clock */
257         
258         update_wall_clock ();
259         Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
260
261         update_disk_space ();
262         update_cpu_load ();
263         update_sample_rate (engine->frame_rate());
264
265         starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
266         stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
267 }
268
269 ARDOUR_UI::~ARDOUR_UI ()
270 {
271         save_ardour_state ();
272
273         if (keyboard) {
274                 delete keyboard;
275         }
276
277         if (editor) {
278                 delete editor;
279         }
280
281         if (mixer) {
282                 delete mixer;
283         }
284
285         if (add_route_dialog) {
286                 delete add_route_dialog;
287         }
288
289         AudioSource::stop_peak_thread ();
290 }
291
292 gint
293 ARDOUR_UI::configure_timeout ()
294 {
295         struct timeval now;
296         struct timeval diff;
297
298         if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
299                 /* no configure events yet */
300                 return TRUE;
301         }
302
303         gettimeofday (&now, 0);
304         timersub (&now, &last_configure_time, &diff);
305
306         /* force a gap of 0.5 seconds since the last configure event
307          */
308
309         if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
310                 return TRUE;
311         } else {
312                 have_configure_timeout = false;
313                 save_ardour_state ();
314                 return FALSE;
315         }
316 }
317
318 gboolean
319 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
320 {
321         if (have_configure_timeout) {
322                 gettimeofday (&last_configure_time, 0);
323         } else {
324                 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
325                 have_configure_timeout = true;
326         }
327                 
328         return FALSE;
329 }
330
331 void
332 ARDOUR_UI::save_ardour_state ()
333 {
334         if (!keyboard || !mixer || !editor) {
335                 return;
336         }
337         
338         /* XXX this is all a bit dubious. add_extra_xml() uses
339            a different lifetime model from add_instant_xml().
340         */
341
342         XMLNode* node = new XMLNode (keyboard->get_state());
343         Config->add_extra_xml (*node);
344         Config->save_state();
345
346         XMLNode enode(static_cast<Stateful*>(editor)->get_state());
347         XMLNode mnode(mixer->get_state());
348
349         if (session) {
350                 session->add_instant_xml (enode, session->path());
351                 session->add_instant_xml (mnode, session->path());
352         } else {
353                 Config->add_instant_xml (enode, get_user_ardour_path());
354                 Config->add_instant_xml (mnode, get_user_ardour_path());
355         }
356
357         save_keybindings ();
358 }
359
360 void
361 ARDOUR_UI::startup ()
362 {
363         // relax
364 }
365
366 void
367 ARDOUR_UI::finish()
368 {
369         if (session && session->dirty()) {
370                 switch (ask_about_saving_session(_("quit"))) {
371                 case -1:
372                         return;
373                         break;
374                 case 1:
375                         /* use the default name */
376                         if (save_state_canfail ("")) {
377                                 /* failed - don't quit */
378                                 MessageDialog msg (*editor, 
379                                                _("\
380 Ardour was unable to save your session.\n\n\
381 If you still wish to quit, please use the\n\n\
382 \"Just quit\" option."));
383                                 msg.run ();
384                                 return;
385                         }
386                         break;
387                 case 0:
388                         break;
389                 }
390         }
391
392         if (session) {
393                 session->set_deletion_in_progress ();
394         }
395         engine->stop (true);
396         Config->save_state();
397         quit ();
398 }
399
400 int
401 ARDOUR_UI::ask_about_saving_session (const string & what)
402 {
403         ArdourDialog window (_("ardour: save session?"));
404         Gtk::HBox dhbox;  // the hbox for the image and text
405         Gtk::Label  prompt_label;
406         Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING,  Gtk::ICON_SIZE_DIALOG));
407
408         string msg;
409
410         msg = string_compose(_("Don't %1"), what);
411         window.add_button (msg, RESPONSE_REJECT);
412         msg = string_compose(_("Just %1"), what);
413         window.add_button (msg, RESPONSE_APPLY);
414         msg = string_compose(_("Save and %1"), what);
415         window.add_button (msg, RESPONSE_ACCEPT);
416
417         window.set_default_response (RESPONSE_ACCEPT);
418
419         Gtk::Button noquit_button (msg);
420         noquit_button.set_name ("EditorGTKButton");
421
422         string prompt;
423         string type;
424
425         if (session->snap_name() == session->name()) {
426                 type = _("session");
427         } else {
428                 type = _("snapshot");
429         }
430         prompt = string_compose(_("The %1\"%2\"\nhas not been saved.\n\nAny changes made this time\nwill be lost unless you save it.\n\nWhat do you want to do?"), 
431                          type, session->snap_name());
432         
433         prompt_label.set_text (prompt);
434         prompt_label.set_name (X_("PrompterLabel"));
435         prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
436
437         dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP)
438 ;
439         dhbox.set_homogeneous (false);
440         dhbox.pack_start (*dimage, false, false, 5);
441         dhbox.pack_start (prompt_label, true, false, 5);
442         window.get_vbox()->pack_start (dhbox);
443
444         window.set_name (_("Prompter"));
445         window.set_position (Gtk::WIN_POS_MOUSE);
446         window.set_modal (true);
447         window.set_resizable (false);
448         window.show_all ();
449
450         save_the_session = 0;
451
452         window.set_keep_above (true);
453         window.present ();
454
455         ResponseType r = (ResponseType) window.run();
456
457         window.hide ();
458
459         switch (r) {
460         case RESPONSE_ACCEPT: // save and get out of here
461                 return 1;
462         case RESPONSE_APPLY:  // get out of here
463                 return 0;
464         default:
465                 break;
466         }
467
468         return -1;
469 }
470         
471 gint
472 ARDOUR_UI::every_second ()
473 {
474         update_cpu_load ();
475         update_buffer_load ();
476         update_disk_space ();
477         return TRUE;
478 }
479
480 gint
481 ARDOUR_UI::every_point_one_seconds ()
482 {
483         update_speed_display ();
484         RapidScreenUpdate(); /* EMIT_SIGNAL */
485         return TRUE;
486 }
487
488 gint
489 ARDOUR_UI::every_point_zero_one_seconds ()
490 {
491         SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
492         return TRUE;
493 }
494
495 void
496 ARDOUR_UI::update_sample_rate (nframes_t ignored)
497 {
498         char buf[32];
499
500         ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
501
502         if (!engine->connected()) {
503
504                 snprintf (buf, sizeof (buf), _("disconnected"));
505
506         } else {
507
508                 nframes_t rate = engine->frame_rate();
509                 
510                 if (fmod (rate, 1000.0) != 0.0) {
511                         snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f msecs"), 
512                                   (float) rate/1000.0f,
513                                   (engine->frames_per_cycle() / (float) rate) * 1000.0f);
514                 } else {
515                         snprintf (buf, sizeof (buf), _("%u kHz / %4.1f msecs"), 
516                                   rate/1000,
517                                   (engine->frames_per_cycle() / (float) rate) * 1000.0f);
518                 }
519         }
520
521         sample_rate_label.set_text (buf);
522 }
523
524 void
525 ARDOUR_UI::update_cpu_load ()
526 {
527         char buf[32];
528         snprintf (buf, sizeof (buf), _("DSP: %.1f%%"), engine->get_cpu_load());
529         cpu_load_label.set_text (buf);
530 }
531
532 void
533 ARDOUR_UI::update_buffer_load ()
534 {
535         char buf[64];
536
537         if (session) {
538                 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"), 
539                           session->playback_load(), session->capture_load());
540                 buffer_load_label.set_text (buf);
541         } else {
542                 buffer_load_label.set_text ("");
543         }
544 }
545
546 void
547 ARDOUR_UI::count_recenabled_streams (Route& route)
548 {
549         Track* track = dynamic_cast<Track*>(&route);
550         if (track && track->diskstream()->record_enabled()) {
551                 rec_enabled_streams += track->n_inputs();
552         }
553 }
554
555 void
556 ARDOUR_UI::update_disk_space()
557 {
558         if (session == 0) {
559                 return;
560         }
561
562         nframes_t frames = session->available_capture_duration();
563         char buf[64];
564
565         if (frames == max_frames) {
566                 strcpy (buf, _("Disk: 24hrs+"));
567         } else {
568                 int hrs;
569                 int mins;
570                 int secs;
571                 nframes_t fr = session->frame_rate();
572                 
573                 rec_enabled_streams = 0;
574                 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
575                 
576                 if (rec_enabled_streams) {
577                         frames /= rec_enabled_streams;
578                 }
579                 
580                 hrs  = frames / (fr * 3600);
581                 frames -= hrs * fr * 3600;
582                 mins = frames / (fr * 60);
583                 frames -= mins * fr * 60;
584                 secs = frames / fr;
585                 
586                 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
587         }
588
589         disk_space_label.set_text (buf);
590 }                 
591
592 gint
593 ARDOUR_UI::update_wall_clock ()
594 {
595         time_t now;
596         struct tm *tm_now;
597         char buf[16];
598
599         time (&now);
600         tm_now = localtime (&now);
601
602         sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
603         wall_clock_label.set_text (buf);
604
605         return TRUE;
606 }
607 void
608 ARDOUR_UI::control_methods_adjusted ()
609
610 {
611         int which_method;
612
613         which_method = (int) online_control_button->adjustment.get_value();
614         switch (which_method) {
615         case 0:
616                 allow_mmc_and_local ();
617                 break;
618         case 1:
619                 allow_mmc_only ();
620                 break;
621         case 2:
622                 allow_local_only ();
623                 break;
624         default:
625                 fatal << _("programming error: impossible control method") << endmsg;
626         }
627 }
628         
629
630 void
631 ARDOUR_UI::mmc_device_id_adjusted ()
632
633 {
634 #if 0
635         if (mmc) {
636                 int dev_id = (int) mmc_id_button->adjustment.get_value();
637                 mmc->set_device_id (dev_id);
638         }
639 #endif
640 }
641
642 gint
643 ARDOUR_UI::session_menu (GdkEventButton *ev)
644 {
645         session_popup_menu->popup (0, 0);
646         return TRUE;
647 }
648
649 void
650 ARDOUR_UI::redisplay_recent_sessions ()
651 {
652         vector<string *> *sessions;
653         vector<string *>::iterator i;
654         RecentSessionsSorter cmp;
655         
656         recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
657         recent_session_model->clear ();
658
659         RecentSessions rs;
660         ARDOUR::read_recent_sessions (rs);
661
662         if (rs.empty()) {
663                 recent_session_display.set_model (recent_session_model);
664                 return;
665         }
666
667         /* sort them alphabetically */
668         sort (rs.begin(), rs.end(), cmp);
669         sessions = new vector<string*>;
670
671         for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
672                 sessions->push_back (new string ((*i).second));
673         }
674
675         for (i = sessions->begin(); i != sessions->end(); ++i) {
676
677                 vector<string*>* states;
678                 vector<const gchar*> item;
679                 string fullpath = *(*i);
680                 
681                 /* remove any trailing / */
682
683                 if (fullpath[fullpath.length()-1] == '/') {
684                         fullpath = fullpath.substr (0, fullpath.length()-1);
685                 }
686
687                 /* now get available states for this session */
688
689                 if ((states = Session::possible_states (fullpath)) == 0) {
690                         /* no state file? */
691                         continue;
692                 }
693
694                 TreeModel::Row row = *(recent_session_model->append());
695
696                 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
697                 row[recent_session_columns.fullpath] = fullpath;
698
699                 if (states->size() > 1) {
700
701                         /* add the children */
702                         
703                         for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
704                                 
705                                 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
706
707                                 child_row[recent_session_columns.visible_name] = **i2;
708                                 child_row[recent_session_columns.fullpath] = fullpath;
709
710                                 delete *i2;
711                         }
712                 }
713
714                 delete states;
715         }
716
717         recent_session_display.set_model (recent_session_model);
718         delete sessions;
719 }
720
721 void
722 ARDOUR_UI::build_session_selector ()
723 {
724         session_selector_window = new ArdourDialog ("session selector");
725         
726         Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
727         
728         session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
729         session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
730         session_selector_window->set_default_response (RESPONSE_ACCEPT);
731         recent_session_model = TreeStore::create (recent_session_columns);
732         recent_session_display.set_model (recent_session_model);
733         recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
734         recent_session_display.set_headers_visible (false);
735         recent_session_display.get_selection()->set_mode (SELECTION_SINGLE);
736
737         recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
738
739         scroller->add (recent_session_display);
740         scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
741
742         session_selector_window->set_name ("SessionSelectorWindow");
743         session_selector_window->set_size_request (200, 400);
744         session_selector_window->get_vbox()->pack_start (*scroller);
745         session_selector_window->show_all_children();
746 }
747
748 void
749 ARDOUR_UI::recent_session_row_activated (const TreePath& path, TreeViewColumn* col)
750 {
751         session_selector_window->response (RESPONSE_ACCEPT);
752 }
753
754 void
755 ARDOUR_UI::open_recent_session ()
756 {
757         /* popup selector window */
758
759         if (session_selector_window == 0) {
760                 build_session_selector ();
761         }
762
763         redisplay_recent_sessions ();
764
765         ResponseType r = (ResponseType) session_selector_window->run ();
766
767         session_selector_window->hide();
768
769         switch (r) {
770         case RESPONSE_ACCEPT:
771                 break;
772         default:
773                 return;
774         }
775
776         Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
777
778         if (i == recent_session_model->children().end()) {
779                 return;
780         }
781         
782         Glib::ustring path = (*i)[recent_session_columns.fullpath];
783         Glib::ustring state = (*i)[recent_session_columns.visible_name];
784
785         _session_is_new = false;
786
787         load_session (path, state);
788 }
789
790 bool
791 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info) 
792 {
793         struct stat statbuf;
794
795         if (stat (info.filename.c_str(), &statbuf) != 0) {
796                 return false;
797         }
798
799         if (!S_ISDIR(statbuf.st_mode)) {
800                 return false;
801         }
802
803         // XXX Portability
804         
805         string session_file = info.filename;
806         session_file += '/';
807         session_file += Glib::path_get_basename (info.filename);
808         session_file += ".ardour";
809         
810         if (stat (session_file.c_str(), &statbuf) != 0) {
811                 return false;
812         }
813
814         return S_ISREG (statbuf.st_mode);
815 }
816
817 void
818 ARDOUR_UI::open_session ()
819 {
820         /* popup selector window */
821
822         if (open_session_selector == 0) {
823
824                 /* ardour sessions are folders */
825
826                 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
827                 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
828                 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
829
830                 FileFilter session_filter;
831                 session_filter.add_pattern ("*.ardour");
832                 session_filter.set_name (_("Ardour sessions"));
833                 open_session_selector->add_filter (session_filter);
834                 open_session_selector->set_filter (session_filter);
835         }
836
837         int response = open_session_selector->run();
838         open_session_selector->hide ();
839
840         switch (response) {
841         case RESPONSE_ACCEPT:
842                 break;
843         default:
844                 open_session_selector->hide();
845                 return;
846         }
847
848         open_session_selector->hide();
849         string session_path = open_session_selector->get_filename();
850         string path, name;
851         bool isnew;
852
853         if (session_path.length() > 0) {
854                 if (Session::find_session (session_path, path, name, isnew) == 0) {
855                         _session_is_new = isnew;
856                         load_session (path, name);
857                 }
858         }
859 }
860
861
862 void
863 ARDOUR_UI::session_add_midi_track ()
864 {
865         cerr << _("Patience is a virtue.\n");
866 }
867
868 void
869 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
870 {
871         list<boost::shared_ptr<AudioTrack> > tracks;
872         Session::RouteList routes;
873
874         if (session == 0) {
875                 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
876                 return;
877         }
878
879         try { 
880                 if (track) {
881                         tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
882
883                         if (tracks.size() != how_many) {
884                                 if (how_many == 1) {
885                                         error << _("could not create a new audio track") << endmsg;
886                                 } else {
887                                         error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
888                                 }
889                         }
890
891                 } else {
892
893                         routes = session->new_audio_route (input_channels, output_channels, how_many);
894
895                         if (routes.size() != how_many) {
896                                 if (how_many == 1) {
897                                         error << _("could not create a new audio track") << endmsg;
898                                 } else {
899                                         error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
900                                 }
901                         }
902                 }
903                 
904 #if CONTROLOUTS
905                 if (need_control_room_outs) {
906                         pan_t pans[2];
907                         
908                         pans[0] = 0.5;
909                         pans[1] = 0.5;
910                         
911                         route->set_stereo_control_outs (control_lr_channels);
912                         route->control_outs()->set_stereo_pan (pans, this);
913                 }
914 #endif /* CONTROLOUTS */
915         }
916
917         catch (...) {
918                 MessageDialog msg (*editor, 
919                                    _("There are insufficient JACK ports available\n\
920 to create a new track or bus.\n\
921 You should save Ardour, exit and\n\
922 restart JACK with more ports."));
923                 msg.run ();
924         }
925 }
926
927 void
928 ARDOUR_UI::do_transport_locate (nframes_t new_position)
929 {
930         nframes_t _preroll = 0;
931
932         if (session) {
933                 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
934                 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
935
936                 if (new_position > _preroll) {
937                         new_position -= _preroll;
938                 } else {
939                         new_position = 0;
940                 }
941
942                 session->request_locate (new_position);
943         }
944 }
945
946 void
947 ARDOUR_UI::transport_goto_start ()
948 {
949         if (session) {
950                 session->goto_start();
951
952                 
953                 /* force displayed area in editor to start no matter
954                    what "follow playhead" setting is.
955                 */
956                 
957                 if (editor) {
958                         editor->reposition_x_origin (session->current_start_frame());
959                 }
960         }
961 }
962
963 void
964 ARDOUR_UI::transport_goto_zero ()
965 {
966         if (session) {
967                 session->request_locate (0);
968
969                 
970                 /* force displayed area in editor to start no matter
971                    what "follow playhead" setting is.
972                 */
973                 
974                 if (editor) {
975                         editor->reposition_x_origin (0);
976                 }
977         }
978 }
979
980 void
981 ARDOUR_UI::transport_goto_end ()
982 {
983         if (session) {
984                 nframes_t frame = session->current_end_frame();
985                 session->request_locate (frame);
986
987                 /* force displayed area in editor to start no matter
988                    what "follow playhead" setting is.
989                 */
990                 
991                 if (editor) {
992                         editor->reposition_x_origin (frame);
993                 }
994         }
995 }
996
997 void
998 ARDOUR_UI::transport_stop ()
999 {
1000         if (!session) {
1001                 return;
1002         }
1003
1004         if (session->is_auditioning()) {
1005                 session->cancel_audition ();
1006                 return;
1007         }
1008         
1009         if (session->get_play_loop ()) {
1010                 session->request_play_loop (false);
1011         }
1012         
1013         session->request_stop ();
1014 }
1015
1016 void
1017 ARDOUR_UI::transport_stop_and_forget_capture ()
1018 {
1019         if (session) {
1020                 session->request_stop (true);
1021         }
1022 }
1023
1024 void
1025 ARDOUR_UI::remove_last_capture()
1026 {
1027         if (editor) {
1028                 editor->remove_last_capture();
1029         }
1030 }
1031
1032 void
1033 ARDOUR_UI::transport_record ()
1034 {
1035         if (session) {
1036                 switch (session->record_status()) {
1037                 case Session::Disabled:
1038                         if (session->ntracks() == 0) {
1039                                 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1040                                 msg.run ();
1041                                 return;
1042                         }
1043                         session->maybe_enable_record ();
1044                         break;
1045                 case Session::Recording:
1046                 case Session::Enabled:
1047                         session->disable_record (true);
1048                 }
1049         }
1050 }
1051
1052 void
1053 ARDOUR_UI::transport_roll ()
1054 {
1055         bool rolling;
1056
1057         if (!session) {
1058                 return;
1059         }
1060
1061         rolling = session->transport_rolling ();
1062
1063         if (session->get_play_loop()) {
1064                 session->request_play_loop (false);
1065                 auto_loop_button.set_active (false);
1066                 roll_button.set_active (true);
1067         } else if (session->get_play_range ()) {
1068                 session->request_play_range (false);
1069                 play_selection_button.set_active (false);
1070         } else if (rolling) {
1071                 session->request_locate (session->last_transport_start(), true);
1072         }
1073
1074         session->request_transport_speed (1.0f);
1075 }
1076
1077 void
1078 ARDOUR_UI::transport_loop()
1079 {
1080         if (session) {
1081                 if (session->get_play_loop()) {
1082                         if (session->transport_rolling()) {
1083                                 Location * looploc = session->locations()->auto_loop_location();
1084                                 if (looploc) {
1085                                         session->request_locate (looploc->start(), true);
1086                                 }
1087                         }
1088                 }
1089                 else {
1090                         session->request_play_loop (true);
1091                 }
1092         }
1093 }
1094
1095 void
1096 ARDOUR_UI::transport_play_selection ()
1097 {
1098         if (!session) {
1099                 return;
1100         }
1101
1102         if (!session->get_play_range()) {
1103                 session->request_stop ();
1104         }
1105
1106         editor->play_selection ();
1107 }
1108
1109 void
1110 ARDOUR_UI::transport_rewind (int option)
1111 {
1112         float current_transport_speed;
1113  
1114         if (session) {
1115                 current_transport_speed = session->transport_speed();
1116                 
1117                 if (current_transport_speed >= 0.0f) {
1118                         switch (option) {
1119                         case 0:
1120                                 session->request_transport_speed (-1.0f);
1121                                 break;
1122                         case 1:
1123                                 session->request_transport_speed (-4.0f);
1124                                 break;
1125                         case -1:
1126                                 session->request_transport_speed (-0.5f);
1127                                 break;
1128                         }
1129                 } else {
1130                         /* speed up */
1131                         session->request_transport_speed (current_transport_speed * 1.5f);
1132                 }
1133         }
1134 }
1135
1136 void
1137 ARDOUR_UI::transport_forward (int option)
1138 {
1139         float current_transport_speed;
1140         
1141         if (session) {
1142                 current_transport_speed = session->transport_speed();
1143                 
1144                 if (current_transport_speed <= 0.0f) {
1145                         switch (option) {
1146                         case 0:
1147                                 session->request_transport_speed (1.0f);
1148                                 break;
1149                         case 1:
1150                                 session->request_transport_speed (4.0f);
1151                                 break;
1152                         case -1:
1153                                 session->request_transport_speed (0.5f);
1154                                 break;
1155                         }
1156                 } else {
1157                         /* speed up */
1158                         session->request_transport_speed (current_transport_speed * 1.5f);
1159                 }
1160         }
1161 }
1162
1163 void
1164 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1165 {
1166         if (session == 0) {
1167                 return;
1168         }
1169
1170         boost::shared_ptr<Route> r;
1171         
1172         if ((r = session->route_by_remote_id (dstream)) != 0) {
1173
1174                 Track* t;
1175
1176                 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1177                         t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1178                 }
1179         }
1180         if (session == 0) {
1181                 return;
1182         }
1183 }
1184
1185 void
1186 ARDOUR_UI::queue_transport_change ()
1187 {
1188         Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1189 }
1190
1191 void
1192 ARDOUR_UI::map_transport_state ()
1193 {
1194         float sp = session->transport_speed();
1195
1196         if (sp == 1.0f) {
1197                 transport_rolling ();
1198         } else if (sp < 0.0f) {
1199                 transport_rewinding ();
1200         } else if (sp > 0.0f) {
1201                 transport_forwarding ();
1202         } else {
1203                 transport_stopped ();
1204         }
1205 }
1206
1207 void
1208 ARDOUR_UI::allow_local_only ()
1209 {
1210
1211 }
1212
1213 void
1214 ARDOUR_UI::allow_mmc_only ()
1215 {
1216
1217 }
1218
1219 void
1220 ARDOUR_UI::allow_mmc_and_local ()
1221 {
1222
1223 }
1224
1225 void
1226 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1227 {
1228         snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1229                 (int) adj.get_value()].c_str());
1230 }
1231
1232 void
1233 ARDOUR_UI::engine_stopped ()
1234 {
1235         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1236         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1237         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1238 }
1239
1240 void
1241 ARDOUR_UI::engine_running ()
1242 {
1243         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1244         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1245         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1246 }
1247
1248 void
1249 ARDOUR_UI::engine_halted ()
1250 {
1251         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1252
1253         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1254         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1255
1256         update_sample_rate (0);
1257
1258         MessageDialog msg (*editor, 
1259                            _("\
1260 JACK has either been shutdown or it\n\
1261 disconnected Ardour because Ardour\n\
1262 was not fast enough. You can save the\n\
1263 session and/or try to reconnect to JACK ."));
1264         msg.run ();
1265 }
1266
1267 int32_t
1268 ARDOUR_UI::do_engine_start ()
1269 {
1270         try { 
1271                 engine->start();
1272         }
1273
1274         catch (...) {
1275                 engine->stop ();
1276                 error << _("Unable to start the session running")
1277                       << endmsg;
1278                 unload_session ();
1279                 return -2;
1280         }
1281         
1282         return 0;
1283 }
1284
1285 gint
1286 ARDOUR_UI::start_engine ()
1287 {
1288         if (do_engine_start () == 0) {
1289                 if (session && _session_is_new) {
1290                         /* we need to retain initial visual 
1291                            settings for a new session 
1292                         */
1293                         session->save_state ("");
1294                 }
1295         }
1296
1297         return FALSE;
1298 }
1299
1300 void
1301 ARDOUR_UI::update_clocks ()
1302 {
1303         if (!editor || !editor->dragging_playhead()) {
1304                 Clock (session->audible_frame()); /* EMIT_SIGNAL */
1305         }
1306 }
1307
1308 void
1309 ARDOUR_UI::start_clocking ()
1310 {
1311         clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1312 }
1313
1314 void
1315 ARDOUR_UI::stop_clocking ()
1316 {
1317         clock_signal_connection.disconnect ();
1318 }
1319         
1320 void
1321 ARDOUR_UI::toggle_clocking ()
1322 {
1323 #if 0
1324         if (clock_button.get_active()) {
1325                 start_clocking ();
1326         } else {
1327                 stop_clocking ();
1328         }
1329 #endif
1330 }
1331
1332 gint
1333 ARDOUR_UI::_blink (void *arg)
1334
1335 {
1336         ((ARDOUR_UI *) arg)->blink ();
1337         return TRUE;
1338 }
1339
1340 void
1341 ARDOUR_UI::blink ()
1342 {
1343          Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1344 }
1345
1346 void
1347 ARDOUR_UI::start_blinking ()
1348 {
1349         /* Start the blink signal. Everybody with a blinking widget
1350            uses Blink to drive the widget's state.
1351         */
1352
1353         if (blink_timeout_tag < 0) {
1354                 blink_on = false;       
1355                 blink_timeout_tag = g_timeout_add (240, _blink, this);
1356         }
1357 }
1358
1359 void
1360 ARDOUR_UI::stop_blinking ()
1361 {
1362         if (blink_timeout_tag >= 0) {
1363                 g_source_remove (blink_timeout_tag);
1364                 blink_timeout_tag = -1;
1365         }
1366 }
1367
1368 void
1369 ARDOUR_UI::name_io_setup (AudioEngine& engine, 
1370                           string& buf,
1371                           IO& io,
1372                           bool in)
1373 {
1374         if (in) {
1375                 if (io.n_inputs() == 0) {
1376                         buf = _("none");
1377                         return;
1378                 }
1379                 
1380                 /* XXX we're not handling multiple ports yet. */
1381
1382                 const char **connections = io.input(0)->get_connections();
1383                 
1384                 if (connections == 0 || connections[0] == '\0') {
1385                         buf = _("off");
1386                 } else {
1387                         buf = connections[0];
1388                 }
1389
1390                 free (connections);
1391
1392         } else {
1393
1394                 if (io.n_outputs() == 0) {
1395                         buf = _("none");
1396                         return;
1397                 }
1398                 
1399                 /* XXX we're not handling multiple ports yet. */
1400
1401                 const char **connections = io.output(0)->get_connections();
1402                 
1403                 if (connections == 0 || connections[0] == '\0') {
1404                         buf = _("off");
1405                 } else {
1406                         buf = connections[0];
1407                 }
1408
1409                 free (connections);
1410         }
1411 }
1412
1413 void
1414 ARDOUR_UI::snapshot_session ()
1415 {
1416         ArdourPrompter prompter (true);
1417         string snapname;
1418         string now;
1419         time_t n;
1420
1421         time (&n);
1422         now = ctime (&n);
1423         now = now.substr (20, 4) + now.substr (3, 16) + " (" + now.substr (0, 3) + ")";
1424
1425         prompter.set_name ("Prompter");
1426         prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1427         prompter.set_prompt (_("Name of New Snapshot"));
1428         prompter.set_initial_text (now);
1429         
1430         switch (prompter.run()) {
1431         case RESPONSE_ACCEPT:
1432                 prompter.get_result (snapname);
1433                 if (snapname.length()){
1434                         save_state (snapname);
1435                 }
1436                 break;
1437
1438         default:
1439                 break;
1440         }
1441 }
1442
1443 void
1444 ARDOUR_UI::save_state (const string & name)
1445 {
1446         (void) save_state_canfail (name);
1447 }
1448                 
1449 int
1450 ARDOUR_UI::save_state_canfail (string name)
1451 {
1452         if (session) {
1453                 int ret;
1454
1455                 if (name.length() == 0) {
1456                         name = session->snap_name();
1457                 }
1458
1459                 if ((ret = session->save_state (name)) != 0) {
1460                         return ret;
1461                 }
1462         }
1463         save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1464         return 0;
1465 }
1466
1467 void
1468 ARDOUR_UI::restore_state (string name)
1469 {
1470         if (session) {
1471                 if (name.length() == 0) {
1472                         name = session->name();
1473                 }
1474                 session->restore_state (name);
1475         }
1476 }
1477
1478 void
1479 ARDOUR_UI::primary_clock_value_changed ()
1480 {
1481         if (session) {
1482                 session->request_locate (primary_clock.current_time ());
1483         }
1484 }
1485
1486 void
1487 ARDOUR_UI::secondary_clock_value_changed ()
1488 {
1489         if (session) {
1490                 session->request_locate (secondary_clock.current_time ());
1491         }
1492 }
1493
1494 void
1495 ARDOUR_UI::rec_enable_button_blink (bool onoff, AudioDiskstream *dstream, Widget *w)
1496 {
1497         if (session && dstream && dstream->record_enabled()) {
1498
1499                 Session::RecordState rs;
1500                 
1501                 rs = session->record_status ();
1502
1503                 switch (rs) {
1504                 case Session::Disabled:
1505                 case Session::Enabled:
1506                         if (w->get_state() != STATE_SELECTED) {
1507                                 w->set_state (STATE_SELECTED);
1508                         }
1509                         break;
1510
1511                 case Session::Recording:
1512                         if (w->get_state() != STATE_ACTIVE) {
1513                                 w->set_state (STATE_ACTIVE);
1514                         }
1515                         break;
1516                 }
1517
1518         } else {
1519                 if (w->get_state() != STATE_NORMAL) {
1520                         w->set_state (STATE_NORMAL);
1521                 }
1522         }
1523 }
1524
1525 void
1526 ARDOUR_UI::transport_rec_enable_blink (bool onoff) 
1527 {
1528         if (session == 0) {
1529                 return;
1530         }
1531         
1532         switch (session->record_status()) {
1533         case Session::Enabled:
1534                 if (onoff) {
1535                         rec_button.set_state (1);
1536                 } else {
1537                         rec_button.set_state (0);
1538                 }
1539                 break;
1540
1541         case Session::Recording:
1542                 rec_button.set_state (2);
1543                 break;
1544
1545         default:
1546                 rec_button.set_state (0);
1547                 break;
1548         }
1549 }
1550
1551 gint
1552 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
1553 {
1554         window->hide();
1555         Gtk::Main::quit ();
1556         return TRUE;
1557 }
1558
1559 void
1560 ARDOUR_UI::start_keyboard_prefix ()
1561 {
1562         keyboard->start_prefix();
1563 }
1564
1565 void
1566 ARDOUR_UI::save_template ()
1567
1568 {
1569         ArdourPrompter prompter (true);
1570         string name;
1571
1572         prompter.set_name (X_("Prompter"));
1573         prompter.set_prompt (_("Name for mix template:"));
1574         prompter.set_initial_text(session->name() + _("-template"));
1575         prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1576
1577         switch (prompter.run()) {
1578         case RESPONSE_ACCEPT:
1579                 prompter.get_result (name);
1580                 
1581                 if (name.length()) {
1582                         session->save_template (name);
1583                 }
1584                 break;
1585
1586         default:
1587                 break;
1588         }
1589 }
1590
1591 void
1592 ARDOUR_UI::new_session (std::string predetermined_path)
1593 {
1594         string session_name;
1595         string session_path;
1596
1597         int response = Gtk::RESPONSE_NONE;
1598
1599         new_session_dialog->set_modal(true);
1600         new_session_dialog->set_name (predetermined_path);
1601         new_session_dialog->reset_recent();
1602         new_session_dialog->show();
1603
1604         do {
1605                 response = new_session_dialog->run ();
1606                 
1607                 _session_is_new = false;
1608
1609                 if (response == Gtk::RESPONSE_CANCEL || response == Gtk::RESPONSE_DELETE_EVENT) {
1610
1611                         if (!session) {
1612                                 quit();
1613                         }
1614                         new_session_dialog->hide ();
1615                         return;
1616
1617                 } else if (response == Gtk::RESPONSE_NONE) {
1618
1619                         /* Clear was pressed */
1620                         new_session_dialog->reset();
1621
1622                 } else if (response == Gtk::RESPONSE_YES) {
1623
1624                         /* YES  == OPEN, but there's no enum for that */
1625
1626                         session_name = new_session_dialog->session_name();
1627                         
1628                         if (session_name.empty()) {
1629                                 response = Gtk::RESPONSE_NONE;
1630                                 continue;
1631                         } 
1632
1633                         if (session_name[0] == '/' || 
1634                             (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
1635                             (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
1636                                 load_session (Glib::path_get_dirname (session_name), session_name);
1637                         } else {
1638                                 session_path = new_session_dialog->session_folder();
1639                                 load_session (session_path, session_name);
1640                         }
1641                         
1642                 } else if (response == Gtk::RESPONSE_OK) {
1643
1644                         session_name = new_session_dialog->session_name();
1645                         
1646                         if (new_session_dialog->get_current_page() == 1) {
1647                   
1648                                 /* XXX this is a bit of a hack.. 
1649                                    i really want the new sesion dialog to return RESPONSE_YES
1650                                    if we're on page 1 (the load page)
1651                                    Unfortunately i can't see how atm.. 
1652                                 */
1653                                 
1654                                 if (session_name.empty()) {
1655                                         response = Gtk::RESPONSE_NONE;
1656                                         continue;
1657                                 } 
1658                                 
1659                                 if (session_name[0] == '/' || 
1660                                     (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
1661                                     (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
1662                                         load_session (Glib::path_get_dirname (session_name), session_name);
1663                                 } else {
1664                                         session_path = new_session_dialog->session_folder();
1665                                         load_session (session_path, session_name);
1666                                 }
1667                         
1668                         } else {
1669
1670                                 if (session_name.empty()) {
1671                                         response = Gtk::RESPONSE_NONE;
1672                                         continue;
1673                                 } 
1674
1675                                 if (session_name[0] == '/' || 
1676                                     (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
1677                                     (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
1678
1679                                         session_path = Glib::path_get_dirname (session_name);
1680                                         session_name = Glib::path_get_basename (session_name);
1681
1682                                 } else {
1683
1684                                         session_path = new_session_dialog->session_folder();
1685
1686                                 }
1687                                 
1688                                 //XXX This is needed because session constructor wants a 
1689                                 //non-existant path. hopefully this will be fixed at some point.
1690                                 
1691                                 session_path = Glib::build_filename (session_path, session_name);
1692                                                 
1693                                 if (g_file_test (session_path.c_str(), GFileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
1694
1695                                         Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
1696
1697                                         MessageDialog msg (str,
1698                                                            false,
1699                                                            Gtk::MESSAGE_WARNING,
1700                                                            Gtk::BUTTONS_YES_NO,
1701                                                            true);
1702
1703
1704                                         msg.set_name (X_("CleanupDialog"));
1705                                         msg.set_wmclass (X_("existing_session"), "Ardour");
1706                                         msg.set_position (Gtk::WIN_POS_MOUSE);
1707                                         
1708                                         switch (msg.run()) {
1709                                         case RESPONSE_YES:
1710                                                 load_session (session_path, session_name);
1711                                                 goto done;
1712                                                 break;
1713                                         default:
1714                                                 response = RESPONSE_NONE;
1715                                                 new_session_dialog->reset ();
1716                                                 continue;
1717                                         }
1718                                 }
1719
1720                                 _session_is_new = true;
1721
1722                                 std::string template_name = new_session_dialog->session_template_name();
1723                                                 
1724                                 if (new_session_dialog->use_session_template()) {
1725                                                         
1726                                         load_session (session_path, session_name, &template_name);
1727                           
1728                                 } else {
1729                                                         
1730                                         uint32_t cchns;
1731                                         uint32_t mchns;
1732                                         AutoConnectOption iconnect;
1733                                         AutoConnectOption oconnect;
1734                                                         
1735                                         if (new_session_dialog->create_control_bus()) {
1736                                                 cchns = (uint32_t) new_session_dialog->control_channel_count();
1737                                         } else {
1738                                                 cchns = 0;
1739                                         }
1740                                                         
1741                                         if (new_session_dialog->create_master_bus()) {
1742                                                 mchns = (uint32_t) new_session_dialog->master_channel_count();
1743                                         } else {
1744                                                 mchns = 0;
1745                                         }
1746                                                         
1747                                         if (new_session_dialog->connect_inputs()) {
1748                                                 iconnect = AutoConnectPhysical;
1749                                         } else {
1750                                                 iconnect = AutoConnectOption (0);
1751                                         }
1752                                                         
1753                                         /// @todo some minor tweaks.
1754                                                         
1755                                         if (new_session_dialog->connect_outs_to_master()) {
1756                                                 oconnect = AutoConnectMaster;
1757                                         } else if (new_session_dialog->connect_outs_to_physical()) {
1758                                                 oconnect = AutoConnectPhysical;
1759                                         } else {
1760                                                 oconnect = AutoConnectOption (0);
1761                                         } 
1762                                                         
1763                                         uint32_t nphysin = (uint32_t) new_session_dialog->input_limit_count();
1764                                         uint32_t nphysout = (uint32_t) new_session_dialog->output_limit_count();
1765                                                         
1766                                         build_session (session_path,
1767                                                        session_name,
1768                                                        cchns,
1769                                                        mchns,
1770                                                        iconnect,
1771                                                        oconnect,
1772                                                        nphysin,
1773                                                        nphysout, 
1774                                                        engine->frame_rate() * 60 * 5);
1775                                 }
1776                         }
1777                 }
1778                 
1779         } while (response == Gtk::RESPONSE_NONE);
1780
1781   done:
1782         show();
1783         new_session_dialog->get_window()->set_cursor();
1784         new_session_dialog->hide();
1785 }
1786
1787 void
1788 ARDOUR_UI::close_session()
1789 {
1790         unload_session();
1791         new_session ();
1792 }
1793
1794 int
1795 ARDOUR_UI::load_session (const string & path, const string & snap_name, string* mix_template)
1796 {
1797         Session *new_session;
1798         int x;
1799         session_loaded = false;
1800         
1801         x = unload_session ();
1802
1803         if (x < 0) {
1804                 return -1;
1805         } else if (x > 0) {
1806                 return 0;
1807         }
1808
1809         /* if it already exists, we must have write access */
1810
1811         if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
1812                 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
1813                                               "This prevents the session from being loaded."));
1814                 msg.run ();
1815                 return -1;
1816         }
1817
1818         try {
1819                 new_session = new Session (*engine, path, snap_name, mix_template);
1820         }
1821
1822         catch (...) {
1823
1824                 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
1825                 return -1;
1826         }
1827
1828         connect_to_session (new_session);
1829
1830         Config->set_current_owner (ConfigVariableBase::Interface);
1831
1832         session_loaded = true;
1833         
1834         goto_editor_window ();
1835
1836         if (session) {
1837                 session->set_clean ();
1838         }
1839
1840         return 0;
1841 }
1842
1843 int
1844 ARDOUR_UI::build_session (const string & path, const string & snap_name, 
1845                           uint32_t control_channels,
1846                           uint32_t master_channels, 
1847                           AutoConnectOption input_connect,
1848                           AutoConnectOption output_connect,
1849                           uint32_t nphysin,
1850                           uint32_t nphysout,
1851                           nframes_t initial_length)
1852 {
1853         Session *new_session;
1854         int x;
1855
1856         session_loaded = false;
1857         x = unload_session ();
1858         if (x < 0) {
1859                 return -1;
1860         } else if (x > 0) {
1861                 return 0;
1862         }
1863         
1864         _session_is_new = true;
1865
1866         try {
1867                 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
1868                                            control_channels, master_channels, nphysin, nphysout, initial_length);
1869         }
1870
1871         catch (...) {
1872
1873                 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
1874                 return -1;
1875         }
1876
1877         connect_to_session (new_session);
1878
1879         session_loaded = true;
1880         return 0;
1881 }
1882
1883 void
1884 ARDOUR_UI::show ()
1885 {
1886         if (editor) {
1887                 editor->show_window ();
1888                 
1889                 if (!shown_flag) {
1890                         editor->present ();
1891                 }
1892
1893                 shown_flag = true;
1894         }
1895 }
1896
1897 void
1898 ARDOUR_UI::show_splash ()
1899 {
1900         if (about == 0) {
1901                 about = new About();
1902                 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
1903         }
1904         about->present();
1905         flush_pending ();
1906 }
1907
1908 void
1909 ARDOUR_UI::about_signal_response(int response)
1910 {
1911         hide_splash();
1912 }
1913
1914 void
1915 ARDOUR_UI::hide_splash ()
1916 {
1917         if (about) {
1918                 about->get_window()->set_cursor ();
1919                 about->hide();
1920         }
1921 }
1922
1923 void
1924 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
1925 {
1926         size_t removed;
1927
1928         removed = rep.paths.size();
1929
1930         if (removed == 0) {
1931                 MessageDialog msgd (*editor,
1932                                     _("No audio files were ready for cleanup"), 
1933                                     true,
1934                                     Gtk::MESSAGE_INFO,
1935                                     (Gtk::ButtonsType)(Gtk::BUTTONS_OK)  );
1936                 msgd.set_secondary_text (_("If this seems suprising, \n\
1937 check for any existing snapshots.\n\
1938 These may still include regions that\n\
1939 require some unused files to continue to exist."));
1940         
1941                 msgd.run ();
1942                 return;
1943         } 
1944
1945         ArdourDialog results (_("ardour: cleanup"), true, false);
1946         
1947         struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
1948             CleanupResultsModelColumns() { 
1949                     add (visible_name);
1950                     add (fullpath);
1951             }
1952             Gtk::TreeModelColumn<Glib::ustring> visible_name;
1953             Gtk::TreeModelColumn<Glib::ustring> fullpath;
1954         };
1955
1956         
1957         CleanupResultsModelColumns results_columns;
1958         Glib::RefPtr<Gtk::ListStore> results_model;
1959         Gtk::TreeView results_display;
1960         
1961         results_model = ListStore::create (results_columns);
1962         results_display.set_model (results_model);
1963         results_display.append_column (list_title, results_columns.visible_name);
1964
1965         results_display.set_name ("CleanupResultsList");
1966         results_display.set_headers_visible (true);
1967         results_display.set_headers_clickable (false);
1968         results_display.set_reorderable (false);
1969
1970         Gtk::ScrolledWindow list_scroller;
1971         Gtk::Label txt;
1972         Gtk::VBox dvbox;
1973         Gtk::HBox dhbox;  // the hbox for the image and text
1974         Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
1975         Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO,  Gtk::ICON_SIZE_DIALOG));
1976
1977         dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
1978
1979         if (rep.space < 1048576.0f) {
1980                 if (removed > 1) {
1981                   txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
1982                 } else {
1983                         txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
1984                 }
1985         } else {
1986                 if (removed > 1) {
1987                         txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
1988                 } else {
1989                         txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
1990                 }
1991         }
1992
1993         dhbox.pack_start (*dimage, true, false, 5);
1994         dhbox.pack_start (txt, true, false, 5);
1995
1996         for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
1997                 TreeModel::Row row = *(results_model->append());
1998                 row[results_columns.visible_name] = *i;
1999                 row[results_columns.fullpath] = *i;
2000         }
2001         
2002         list_scroller.add (results_display);
2003         list_scroller.set_size_request (-1, 150);
2004         list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2005
2006         dvbox.pack_start (dhbox, true, false, 5);
2007         dvbox.pack_start (list_scroller, true, false, 5);
2008         ddhbox.pack_start (dvbox, true, false, 5);
2009
2010         results.get_vbox()->pack_start (ddhbox, true, false, 5);
2011         results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2012         results.set_default_response (RESPONSE_CLOSE);
2013         results.set_position (Gtk::WIN_POS_MOUSE);
2014         results.show_all_children ();
2015         results.set_resizable (false);
2016
2017         results.run ();
2018
2019 }
2020
2021 void
2022 ARDOUR_UI::cleanup ()
2023 {
2024         if (session == 0) {
2025                 /* shouldn't happen: menu item is insensitive */
2026                 return;
2027         }
2028
2029
2030         MessageDialog  checker (_("Are you sure you want to cleanup?"),
2031                                 true,
2032                                 Gtk::MESSAGE_QUESTION,
2033                                 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2034
2035         checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2036 ALL undo/redo information will be lost if you cleanup.\n\
2037 After cleanup, unused audio files will be moved to a \
2038 \"dead sounds\" location."));
2039         
2040         checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2041         checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2042         checker.set_default_response (RESPONSE_CANCEL);
2043
2044         checker.set_name (_("CleanupDialog"));
2045         checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2046         checker.set_position (Gtk::WIN_POS_MOUSE);
2047
2048         switch (checker.run()) {
2049         case RESPONSE_ACCEPT:
2050                 break;
2051         default:
2052                 return;
2053         }
2054
2055         Session::cleanup_report rep;
2056
2057         editor->prepare_for_cleanup ();
2058
2059         if (session->cleanup_sources (rep)) {
2060                 return;
2061         }
2062         checker.hide();
2063         display_cleanup_results (rep, 
2064                                  _("cleaned files"),
2065                                  _("\
2066 The following %1 %2 not in use and \n\
2067 have been moved to:\n\
2068 %3. \n\n\
2069 Flushing the wastebasket will \n\
2070 release an additional\n\
2071 %4 %5bytes of disk space.\n"
2072                                          ));
2073 }
2074
2075 void
2076 ARDOUR_UI::flush_trash ()
2077 {
2078         if (session == 0) {
2079                 /* shouldn't happen: menu item is insensitive */
2080                 return;
2081         }
2082
2083         Session::cleanup_report rep;
2084
2085         if (session->cleanup_trash_sources (rep)) {
2086                 return;
2087         }
2088
2089         display_cleanup_results (rep, 
2090                                  _("deleted file"),
2091                                  _("The following %1 %2 deleted from\n\
2092 %3,\n\
2093 releasing %4 %5bytes of disk space"));
2094 }
2095
2096 void
2097 ARDOUR_UI::add_route ()
2098 {
2099         int count;
2100
2101         if (!session) {
2102                 return;
2103         }
2104
2105         if (add_route_dialog == 0) {
2106                 add_route_dialog = new AddRouteDialog;
2107                 editor->ensure_float (*add_route_dialog);
2108         }
2109
2110         if (add_route_dialog->is_visible()) {
2111                 /* we're already doing this */
2112                 return;
2113         }
2114
2115         ResponseType r = (ResponseType) add_route_dialog->run ();
2116         
2117         add_route_dialog->hide();
2118
2119         switch (r) {
2120         case RESPONSE_ACCEPT:
2121                 break;
2122         default:
2123                 return;
2124                 break;
2125         }
2126
2127         if ((count = add_route_dialog->count()) <= 0) {
2128                 return;
2129         }
2130
2131         uint32_t input_chan = add_route_dialog->channels ();
2132         uint32_t output_chan;
2133         string name_template = add_route_dialog->name_template ();
2134         bool track = add_route_dialog->track ();
2135
2136         AutoConnectOption oac = Config->get_output_auto_connect();
2137
2138         if (oac & AutoConnectMaster) {
2139                 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
2140         } else {
2141                 output_chan = input_chan;
2142         }
2143
2144         /* XXX do something with name template */
2145
2146         if (track) {
2147                 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2148         } else {
2149                 session_add_audio_bus (input_chan, output_chan, count);
2150         }
2151 }
2152
2153 XMLNode*
2154 ARDOUR_UI::mixer_settings () const
2155 {
2156         XMLNode* node = 0;
2157
2158         if (session) {
2159                 node = session->instant_xml(X_("Mixer"), session->path());
2160         } else {
2161                 node = Config->instant_xml(X_("Mixer"), get_user_ardour_path());
2162         }
2163
2164         if (!node) {
2165                 node = new XMLNode (X_("Mixer"));
2166         }
2167
2168         return node;
2169 }
2170
2171 XMLNode*
2172 ARDOUR_UI::editor_settings () const
2173 {
2174         XMLNode* node = 0;
2175
2176         if (session) {
2177                 node = session->instant_xml(X_("Editor"), session->path());
2178         } else {
2179                 node = Config->instant_xml(X_("Editor"), get_user_ardour_path());
2180         }
2181
2182         if (!node) {
2183                 node = new XMLNode (X_("Editor"));
2184         }
2185         return node;
2186 }
2187
2188 XMLNode*
2189 ARDOUR_UI::keyboard_settings () const
2190 {
2191         XMLNode* node = 0;
2192
2193         node = Config->extra_xml(X_("Keyboard"));
2194         
2195         if (!node) {
2196                 node = new XMLNode (X_("Keyboard"));
2197         }
2198         return node;
2199 }
2200
2201 void
2202 ARDOUR_UI::halt_on_xrun_message ()
2203 {
2204         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
2205
2206         MessageDialog msg (*editor,
2207                            _("Recording was stopped because your system could not keep up."));
2208         msg.run ();
2209 }
2210
2211 void
2212 ARDOUR_UI::disk_overrun_handler ()
2213 {
2214         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2215
2216         if (!have_disk_overrun_displayed) {
2217                 have_disk_overrun_displayed = true;
2218                 MessageDialog msg (*editor, X_("diskrate dialog"), _("\
2219 The disk system on your computer\n\
2220 was not able to keep up with Ardour.\n\
2221 \n\
2222 Specifically, it failed to write data to disk\n\
2223 quickly enough to keep up with recording.\n"));
2224                 msg.run ();
2225                 have_disk_overrun_displayed = false;
2226         }
2227 }
2228
2229 void
2230 ARDOUR_UI::disk_underrun_handler ()
2231 {
2232         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2233
2234         if (!have_disk_underrun_displayed) {
2235                 have_disk_underrun_displayed = true;
2236                 MessageDialog msg (*editor,
2237                         (_("The disk system on your computer\n\
2238 was not able to keep up with Ardour.\n\
2239 \n\
2240 Specifically, it failed to read data from disk\n\
2241 quickly enough to keep up with playback.\n")));
2242                 msg.run ();
2243                 have_disk_underrun_displayed = false;
2244         } 
2245 }
2246
2247 void
2248 ARDOUR_UI::disk_underrun_message_gone ()
2249 {
2250         have_disk_underrun_displayed = false;
2251 }
2252
2253 void
2254 ARDOUR_UI::disk_overrun_message_gone ()
2255 {
2256         have_disk_underrun_displayed = false;
2257 }
2258
2259 int
2260 ARDOUR_UI::pending_state_dialog ()
2261 {
2262         ArdourDialog dialog ("pending state dialog");
2263         Label  message (_("\
2264 This session appears to have been in\n\
2265 middle of recording when ardour or\n\
2266 the computer was shutdown.\n\
2267 \n\
2268 Ardour can recover any captured audio for\n\
2269 you, or it can ignore it. Please decide\n\
2270 what you would like to do.\n"));
2271
2272         dialog.get_vbox()->pack_start (message);
2273         dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
2274         dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
2275
2276         dialog.set_position (WIN_POS_CENTER);
2277         dialog.show_all ();
2278         
2279         switch (dialog.run ()) {
2280         case RESPONSE_ACCEPT:
2281                 return 1;
2282         default:
2283                 return 0;
2284         }
2285 }
2286         
2287 void
2288 ARDOUR_UI::disconnect_from_jack ()
2289 {
2290         if (engine) {
2291                 if( engine->disconnect_from_jack ()) {
2292                         MessageDialog msg (*editor, _("Could not disconnect from JACK"));
2293                         msg.run ();
2294                 }
2295
2296                 update_sample_rate (0);
2297         }
2298 }
2299
2300 void
2301 ARDOUR_UI::reconnect_to_jack ()
2302 {
2303         if (engine) {
2304                 if (engine->reconnect_to_jack ()) {
2305                         MessageDialog msg (*editor,  _("Could not reconnect to JACK"));
2306                         msg.run ();
2307                 }
2308
2309                 update_sample_rate (0);
2310         }
2311 }
2312
2313 void
2314 ARDOUR_UI::set_jack_buffer_size (nframes_t nframes)
2315 {
2316         engine->request_buffer_size (nframes);
2317         update_sample_rate (0);
2318 }
2319
2320 int
2321 ARDOUR_UI::cmdline_new_session (string path)
2322 {
2323         if (path[0] != '/') {
2324                 char buf[PATH_MAX+1];
2325                 string str;
2326
2327                 getcwd (buf, sizeof (buf));
2328                 str = buf;
2329                 str += '/';
2330                 str += path;
2331                 path = str;
2332         }
2333
2334         new_session (path);
2335
2336         _will_create_new_session_automatically = false; /* done it */
2337         return FALSE; /* don't call it again */
2338 }
2339
2340 void
2341 ARDOUR_UI::use_config ()
2342 {
2343         Glib::RefPtr<Action> act;
2344
2345         switch (Config->get_native_file_data_format ()) {
2346         case FormatFloat:
2347                 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
2348                 break;
2349         case FormatInt24:
2350                 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
2351                 break;
2352         }
2353
2354         if (act) {
2355                 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2356                 ract->set_active ();
2357         }       
2358
2359         switch (Config->get_native_file_header_format ()) {
2360         case BWF:
2361                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
2362                 break;
2363         case WAVE:
2364                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
2365                 break;
2366         case WAVE64:
2367                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
2368                 break;
2369         case iXML:
2370                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
2371                 break;
2372         case RF64:
2373                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
2374                 break;
2375         case CAF:
2376                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
2377                 break;
2378         case AIFF:
2379                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
2380                 break;
2381         }
2382
2383         if (act) {
2384                 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2385                 ract->set_active ();
2386         }       
2387 }
2388
2389 void
2390 ARDOUR_UI::update_transport_clocks (nframes_t pos)
2391 {
2392         primary_clock.set (pos);
2393         secondary_clock.set (pos);
2394
2395         if (big_clock_window) {
2396                 big_clock.set (pos);
2397         }
2398 }
2399
2400 void
2401 ARDOUR_UI::record_state_changed ()
2402 {
2403         if (!session || !big_clock_window) {
2404                 /* why bother - the clock isn't visible */
2405                 return;
2406         }
2407
2408         switch (session->record_status()) {
2409         case Session::Recording:
2410                 big_clock.set_widget_name ("BigClockRecording");
2411                 break;
2412         default:
2413                 big_clock.set_widget_name ("BigClockNonRecording");
2414                 break;
2415         }
2416 }
2417
2418 void
2419 ARDOUR_UI::set_keybindings_path (string path)
2420 {
2421         keybindings_path = path;
2422 }
2423
2424 void
2425 ARDOUR_UI::save_keybindings ()
2426 {
2427         if (can_save_keybindings) {
2428                 AccelMap::save (keybindings_path);
2429         } 
2430 }
2431
2432 bool
2433 ARDOUR_UI::first_idle ()
2434 {
2435         can_save_keybindings = true;
2436         return false;
2437 }
2438
2439 void
2440 ARDOUR_UI::store_clock_modes ()
2441 {
2442         XMLNode* node = new XMLNode(X_("ClockModes"));
2443
2444         for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
2445                 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
2446         }
2447
2448         session->add_extra_xml (*node);
2449         session->set_dirty ();
2450 }
2451
2452
2453