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