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