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