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