cross-thread handling of SessionEvent allocation/deallocation, with widespread conseq...
[ardour.git] / gtk2_ardour / ardour_ui.cc
1 /*
2     Copyright (C) 1999-2007 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 */
19
20 #define __STDC_FORMAT_MACROS 1
21 #include <stdint.h>
22
23 #include <algorithm>
24 #include <cmath>
25 #include <fcntl.h>
26 #include <signal.h>
27 #include <unistd.h>
28 #include <time.h>
29 #include <cerrno>
30 #include <fstream>
31
32 #include <iostream>
33
34 #include <sys/resource.h>
35
36 #include <gtkmm/messagedialog.h>
37 #include <gtkmm/accelmap.h>
38
39 #include "pbd/error.h"
40 #include "pbd/basename.h"
41 #include "pbd/compose.h"
42 #include "pbd/failed_constructor.h"
43 #include "pbd/enumwriter.h"
44 #include "pbd/memento_command.h"
45 #include "pbd/file_utils.h"
46
47 #include <gtkmm2ext/gtk_ui.h>
48 #include <gtkmm2ext/utils.h>
49 #include <gtkmm2ext/click_box.h>
50 #include <gtkmm2ext/fastmeter.h>
51 #include <gtkmm2ext/stop_signal.h>
52 #include <gtkmm2ext/popup.h>
53 #include <gtkmm2ext/window_title.h>
54
55 #include "midi++/manager.h"
56
57 #include "ardour/ardour.h"
58 #include "ardour/profile.h"
59 #include "ardour/session_directory.h"
60 #include "ardour/session_route.h"
61 #include "ardour/session_state_utils.h"
62 #include "ardour/session_utils.h"
63 #include "ardour/port.h"
64 #include "ardour/audioengine.h"
65 #include "ardour/playlist.h"
66 #include "ardour/utils.h"
67 #include "ardour/audio_diskstream.h"
68 #include "ardour/audiofilesource.h"
69 #include "ardour/recent_sessions.h"
70 #include "ardour/port.h"
71 #include "ardour/audio_track.h"
72 #include "ardour/midi_track.h"
73 #include "ardour/filesystem_paths.h"
74 #include "ardour/filename_extensions.h"
75
76 typedef uint64_t microseconds_t;
77
78 #include "actions.h"
79 #include "ardour_ui.h"
80 #include "public_editor.h"
81 #include "audio_clock.h"
82 #include "keyboard.h"
83 #include "mixer_ui.h"
84 #include "prompter.h"
85 #include "opts.h"
86 #include "add_route_dialog.h"
87 #include "about.h"
88 #include "splash.h"
89 #include "utils.h"
90 #include "gui_thread.h"
91 #include "theme_manager.h"
92 #include "bundle_manager.h"
93 #include "session_metadata_dialog.h"
94 #include "gain_meter.h"
95 #include "route_time_axis.h"
96 #include "startup.h"
97 #include "engine_dialog.h"
98 #include "processor_box.h"
99
100 #include "i18n.h"
101
102 using namespace ARDOUR;
103 using namespace PBD;
104 using namespace Gtkmm2ext;
105 using namespace Gtk;
106 using namespace sigc;
107
108 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
109 UIConfiguration *ARDOUR_UI::ui_config = 0;
110
111 sigc::signal<void,bool> ARDOUR_UI::Blink;
112 sigc::signal<void>      ARDOUR_UI::RapidScreenUpdate;
113 sigc::signal<void>      ARDOUR_UI::SuperRapidScreenUpdate;
114 sigc::signal<void,nframes_t, bool, nframes_t> ARDOUR_UI::Clock;
115
116 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
117
118         : Gtkmm2ext::UI (X_("Ardour"), argcp, argvp),
119
120           primary_clock (X_("primary"), false, X_("TransportClockDisplay"), true, true, false, true),
121           secondary_clock (X_("secondary"), false, X_("SecondaryClockDisplay"), true, true, false, true),
122           preroll_clock (X_("preroll"), false, X_("PreRollClock"), true, false, true),
123           postroll_clock (X_("postroll"), false, X_("PostRollClock"), true, false, true),
124
125           /* preroll stuff */
126
127           preroll_button (_("pre\nroll")),
128           postroll_button (_("post\nroll")),
129
130           /* big clock */
131
132           big_clock (X_("bigclock"), false, "BigClockNonRecording", true, true, false, true),
133
134           /* transport */
135
136           roll_controllable (new TransportControllable ("transport roll", *this, TransportControllable::Roll)),
137           stop_controllable (new TransportControllable ("transport stop", *this, TransportControllable::Stop)),
138           goto_start_controllable (new TransportControllable ("transport goto start", *this, TransportControllable::GotoStart)),
139           goto_end_controllable (new TransportControllable ("transport goto end", *this, TransportControllable::GotoEnd)),
140           auto_loop_controllable (new TransportControllable ("transport auto loop", *this, TransportControllable::AutoLoop)),
141           play_selection_controllable (new TransportControllable ("transport play selection", *this, TransportControllable::PlaySelection)),
142           rec_controllable (new TransportControllable ("transport rec-enable", *this, TransportControllable::RecordEnable)),
143           shuttle_controllable (new TransportControllable ("shuttle", *this, TransportControllable::ShuttleControl)),
144           shuttle_controller_binding_proxy (shuttle_controllable),
145
146           roll_button (roll_controllable),
147           stop_button (stop_controllable),
148           goto_start_button (goto_start_controllable),
149           goto_end_button (goto_end_controllable),
150           auto_loop_button (auto_loop_controllable),
151           play_selection_button (play_selection_controllable),
152           rec_button (rec_controllable),
153
154           shuttle_units_button (_("% ")),
155
156           punch_in_button (_("Punch In")),
157           punch_out_button (_("Punch Out")),
158           auto_return_button (_("Auto Return")),
159           auto_play_button (_("Auto Play")),
160           auto_input_button (_("Auto Input")),
161           click_button (_("Click")),
162           time_master_button (_("time\nmaster")),
163
164           auditioning_alert_button (_("AUDITION")),
165           solo_alert_button (_("SOLO")),
166           shown_flag (false),
167           error_log_button (_("Errors"))
168
169 {
170         using namespace Gtk::Menu_Helpers;
171
172         Gtkmm2ext::init();
173
174
175 #ifdef TOP_MENUBAR
176         // _auto_display_errors = false;
177         /*
178          * This was commented out as it wasn't defined
179          * in A3 IIRC.  If this is not needed it should
180          * be completely removed.
181          */
182 #endif
183
184         about = 0;
185         splash = 0;
186         _startup = 0;
187
188         if (theArdourUI == 0) {
189                 theArdourUI = this;
190         }
191
192         ui_config = new UIConfiguration();
193         theme_manager = new ThemeManager();
194
195         editor = 0;
196         mixer = 0;
197         session = 0;
198         editor = 0;
199         engine = 0;
200         _session_is_new = false;
201         big_clock_window = 0;
202         session_selector_window = 0;
203         last_key_press_time = 0;
204         _will_create_new_session_automatically = false;
205         add_route_dialog = 0;
206         route_params = 0;
207         rc_option_editor = 0;
208         session_option_editor = 0;
209         location_ui = 0;
210         open_session_selector = 0;
211         have_configure_timeout = false;
212         have_disk_speed_dialog_displayed = false;
213         session_loaded = false;
214         last_speed_displayed = -1.0f;
215         ignore_dual_punch = false;
216         _mixer_on_top = false;
217
218         roll_button.unset_flags (Gtk::CAN_FOCUS);
219         stop_button.unset_flags (Gtk::CAN_FOCUS);
220         goto_start_button.unset_flags (Gtk::CAN_FOCUS);
221         goto_end_button.unset_flags (Gtk::CAN_FOCUS);
222         auto_loop_button.unset_flags (Gtk::CAN_FOCUS);
223         play_selection_button.unset_flags (Gtk::CAN_FOCUS);
224         rec_button.unset_flags (Gtk::CAN_FOCUS);
225
226         last_configure_time= 0;
227
228         shuttle_grabbed = false;
229         shuttle_fract = 0.0;
230         shuttle_max_speed = 8.0f;
231
232         shuttle_style_menu = 0;
233         shuttle_unit_menu = 0;
234
235         // We do not have jack linked in yet so;
236
237         last_shuttle_request = last_peak_grab = 0; //  get_microseconds();
238
239         ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
240         ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
241
242         /* handle dialog requests */
243
244         ARDOUR::Session::Dialog.connect (mem_fun(*this, &ARDOUR_UI::session_dialog));
245
246         /* handle pending state with a dialog */
247
248         ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
249
250         /* handle sr mismatch with a dialog */
251
252         ARDOUR::Session::AskAboutSampleRateMismatch.connect (mem_fun(*this, &ARDOUR_UI::sr_mismatch_dialog));
253
254         /* lets get this party started */
255
256         try {
257                 if (ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst, ARDOUR_COMMAND_LINE::try_hw_optimization)) {
258                         throw failed_constructor ();
259                 }
260
261                 setup_gtk_ardour_enums ();
262                 setup_profile ();
263
264                 GainMeter::setup_slider_pix ();
265                 RouteTimeAxisView::setup_slider_pix ();
266                 SendProcessorEntry::setup_slider_pix ();
267                 SessionEvent::create_per_thread_pool ("GUI", 512);
268
269         } catch (failed_constructor& err) {
270                 error << _("could not initialize Ardour.") << endmsg;
271                 // pass it on up
272                 throw;
273         }
274
275         /* we like keyboards */
276
277         keyboard = new Keyboard;
278
279         reset_dpi();
280
281         starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
282         stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
283
284         platform_setup ();
285 }
286
287 /** @return true if a session was chosen and `apply' clicked, otherwise false if `cancel' was clicked */
288 bool
289 ARDOUR_UI::run_startup (bool should_be_new)
290 {
291         if (_startup == 0) {
292                 _startup = new ArdourStartup ();
293         }
294
295         _startup->set_new_only (should_be_new);
296         _startup->present ();
297
298         main().run();
299
300         _startup->hide ();
301
302         switch (_startup->response()) {
303         case RESPONSE_OK:
304                 return true;
305         default:
306                 return false;
307         }
308 }
309
310 int
311 ARDOUR_UI::create_engine ()
312 {
313         // this gets called every time by new_session()
314
315         if (engine) {
316                 return 0;
317         }
318
319         loading_message (_("Starting audio engine"));
320
321         try {
322                 engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name);
323
324         } catch (...) {
325
326                 return -1;
327         }
328
329         engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
330         engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
331         engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
332         engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
333
334         post_engine ();
335
336         return 0;
337 }
338
339 void
340 ARDOUR_UI::post_engine ()
341 {
342         /* Things to be done once we create the AudioEngine
343          */
344
345         MIDI::Manager::instance()->set_api_data (engine->jack());
346         setup_midi ();
347         
348         ARDOUR::init_post_engine ();
349
350         ActionManager::init ();
351         _tooltips.enable();
352
353         if (setup_windows ()) {
354                 throw failed_constructor ();
355         }
356         
357         check_memory_locking();
358
359         /* this is the first point at which all the keybindings are available */
360
361         if (ARDOUR_COMMAND_LINE::show_key_actions) {
362                 vector<string> names;
363                 vector<string> paths;
364                 vector<string> keys;
365                 vector<AccelKey> bindings;
366
367                 ActionManager::get_all_actions (names, paths, keys, bindings);
368
369                 vector<string>::iterator n;
370                 vector<string>::iterator k;
371                 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
372                         cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
373                 }
374
375                 exit (0);
376         }
377
378         blink_timeout_tag = -1;
379
380         /* this being a GUI and all, we want peakfiles */
381
382         AudioFileSource::set_build_peakfiles (true);
383         AudioFileSource::set_build_missing_peakfiles (true);
384
385         /* set default clock modes */
386
387         if (Profile->get_sae()) {
388                 primary_clock.set_mode (AudioClock::BBT);
389                 secondary_clock.set_mode (AudioClock::MinSec);
390         }  else {
391                 primary_clock.set_mode (AudioClock::Timecode);
392                 secondary_clock.set_mode (AudioClock::BBT);
393         }
394
395         /* start the time-of-day-clock */
396
397 #ifndef GTKOSX
398         /* OS X provides an always visible wallclock, so don't be stupid */
399         update_wall_clock ();
400         Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
401 #endif
402
403         update_disk_space ();
404         update_cpu_load ();
405         update_sample_rate (engine->frame_rate());
406
407         Config->ParameterChanged.connect (mem_fun (*this, &ARDOUR_UI::parameter_changed));
408         Config->map_parameters (mem_fun (*this, &ARDOUR_UI::parameter_changed));
409
410         /* now start and maybe save state */
411
412         if (do_engine_start () == 0) {
413                 if (session && _session_is_new) {
414                         /* we need to retain initial visual
415                            settings for a new session
416                         */
417                         session->save_state ("");
418                 }
419         }
420 }
421
422 ARDOUR_UI::~ARDOUR_UI ()
423 {
424         save_ardour_state ();
425
426         delete keyboard;
427         delete editor;
428         delete mixer;
429         delete add_route_dialog;
430 }
431
432 void
433 ARDOUR_UI::pop_back_splash ()
434 {
435         if (Splash::instance()) {
436                 // Splash::instance()->pop_back();
437                 Splash::instance()->hide ();
438         }
439 }
440
441 gint
442 ARDOUR_UI::configure_timeout ()
443 {
444         if (last_configure_time == 0) {
445                 /* no configure events yet */
446                 return TRUE;
447         }
448
449         /* force a gap of 0.5 seconds since the last configure event
450          */
451
452         if (get_microseconds() - last_configure_time < 500000) {
453                 return TRUE;
454         } else {
455                 have_configure_timeout = false;
456                 save_ardour_state ();
457                 return FALSE;
458         }
459 }
460
461 gboolean
462 ARDOUR_UI::configure_handler (GdkEventConfigure* /*conf*/)
463 {
464         if (have_configure_timeout) {
465                 last_configure_time = get_microseconds();
466         } else {
467                 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
468                 have_configure_timeout = true;
469         }
470
471         return FALSE;
472 }
473
474 void
475 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
476 {
477         const XMLProperty* prop;
478
479         if ((prop = node.property ("roll")) != 0) {
480                 roll_controllable->set_id (prop->value());
481         }
482         if ((prop = node.property ("stop")) != 0) {
483                 stop_controllable->set_id (prop->value());
484         }
485         if ((prop = node.property ("goto-start")) != 0) {
486                 goto_start_controllable->set_id (prop->value());
487         }
488         if ((prop = node.property ("goto-end")) != 0) {
489                 goto_end_controllable->set_id (prop->value());
490         }
491         if ((prop = node.property ("auto-loop")) != 0) {
492                 auto_loop_controllable->set_id (prop->value());
493         }
494         if ((prop = node.property ("play-selection")) != 0) {
495                 play_selection_controllable->set_id (prop->value());
496         }
497         if ((prop = node.property ("rec")) != 0) {
498                 rec_controllable->set_id (prop->value());
499         }
500         if ((prop = node.property ("shuttle")) != 0) {
501                 shuttle_controllable->set_id (prop->value());
502         }
503 }
504
505 XMLNode&
506 ARDOUR_UI::get_transport_controllable_state ()
507 {
508         XMLNode* node = new XMLNode(X_("TransportControllables"));
509         char buf[64];
510
511         roll_controllable->id().print (buf, sizeof (buf));
512         node->add_property (X_("roll"), buf);
513         stop_controllable->id().print (buf, sizeof (buf));
514         node->add_property (X_("stop"), buf);
515         goto_start_controllable->id().print (buf, sizeof (buf));
516         node->add_property (X_("goto_start"), buf);
517         goto_end_controllable->id().print (buf, sizeof (buf));
518         node->add_property (X_("goto_end"), buf);
519         auto_loop_controllable->id().print (buf, sizeof (buf));
520         node->add_property (X_("auto_loop"), buf);
521         play_selection_controllable->id().print (buf, sizeof (buf));
522         node->add_property (X_("play_selection"), buf);
523         rec_controllable->id().print (buf, sizeof (buf));
524         node->add_property (X_("rec"), buf);
525         shuttle_controllable->id().print (buf, sizeof (buf));
526         node->add_property (X_("shuttle"), buf);
527
528         return *node;
529 }
530
531 void
532 ARDOUR_UI::save_ardour_state ()
533 {
534         if (!keyboard || !mixer || !editor) {
535                 return;
536         }
537
538         /* XXX this is all a bit dubious. add_extra_xml() uses
539            a different lifetime model from add_instant_xml().
540         */
541
542         XMLNode* node = new XMLNode (keyboard->get_state());
543         Config->add_extra_xml (*node);
544         Config->add_extra_xml (get_transport_controllable_state());
545         if (_startup && _startup->engine_control() && _startup->engine_control()->was_used()) {
546                 Config->add_extra_xml (_startup->engine_control()->get_state());
547         }
548         Config->save_state();
549         ui_config->save_state ();
550
551         XMLNode enode(static_cast<Stateful*>(editor)->get_state());
552         XMLNode mnode(mixer->get_state());
553
554         if (session) {
555                 session->add_instant_xml (enode);
556                 session->add_instant_xml (mnode);
557         } else {
558                 Config->add_instant_xml (enode);
559                 Config->add_instant_xml (mnode);
560         }
561
562         Keyboard::save_keybindings ();
563 }
564
565 gint
566 ARDOUR_UI::autosave_session ()
567 {
568         if (g_main_depth() > 1) {
569                 /* inside a recursive main loop,
570                    give up because we may not be able to
571                    take a lock.
572                 */
573                 return 1;
574         }
575
576         if (!Config->get_periodic_safety_backups()) {
577                 return 1;
578         }
579
580         if (session) {
581                 session->maybe_write_autosave();
582         }
583
584         return 1;
585 }
586
587 void
588 ARDOUR_UI::update_autosave ()
589 {
590         ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave));
591
592         if (session && session->dirty()) {
593                 if (_autosave_connection.connected()) {
594                         _autosave_connection.disconnect();
595                 }
596
597                 _autosave_connection = Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session),
598                                 Config->get_periodic_safety_backup_interval() * 1000);
599
600         } else {
601                 if (_autosave_connection.connected()) {
602                         _autosave_connection.disconnect();
603                 }
604         }
605 }
606
607 void
608 ARDOUR_UI::backend_audio_error (bool we_set_params, Gtk::Window* toplevel)
609 {
610         string title;
611         if (we_set_params) {
612                 title = _("Ardour could not start JACK");
613         } else {
614                 title = _("Ardour could not connect to JACK.");
615         }
616
617         MessageDialog win (title,
618                            false,
619                            Gtk::MESSAGE_INFO,
620                            Gtk::BUTTONS_NONE);
621
622         if (we_set_params) {
623                 win.set_secondary_text(_("There are several possible reasons:\n\
624 \n\
625 1) You requested audio parameters that are not supported..\n\
626 2) JACK is running as another user.\n\
627 \n\
628 Please consider the possibilities, and perhaps try different parameters."));
629         } else {
630                 win.set_secondary_text(_("There are several possible reasons:\n\
631 \n\
632 1) JACK is not running.\n\
633 2) JACK is running as another user, perhaps root.\n\
634 3) There is already another client called \"ardour\".\n\
635 \n\
636 Please consider the possibilities, and perhaps (re)start JACK."));
637         }
638
639         if (toplevel) {
640                 win.set_transient_for (*toplevel);
641         }
642
643         if (we_set_params) {
644                 win.add_button (Stock::OK, RESPONSE_CLOSE);
645         } else {
646                 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
647         }
648
649         win.set_default_response (RESPONSE_CLOSE);
650
651         win.show_all ();
652         win.set_position (Gtk::WIN_POS_CENTER);
653         pop_back_splash ();
654
655         /* we just don't care about the result, but we want to block */
656
657         win.run ();
658 }
659
660 void
661 ARDOUR_UI::startup ()
662 {
663         XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
664
665         if (audio_setup && _startup && _startup->engine_control()) {
666                 _startup->engine_control()->set_state (*audio_setup);
667         }
668
669         if (get_session_parameters (true, ARDOUR_COMMAND_LINE::new_session)) {
670                 exit (1);
671         }
672
673         use_config ();
674
675         goto_editor_window ();
676
677         BootMessage (_("Ardour is ready for use"));
678         show ();
679 }
680
681 void
682 ARDOUR_UI::no_memory_warning ()
683 {
684         XMLNode node (X_("no-memory-warning"));
685         Config->add_instant_xml (node);
686 }
687
688 void
689 ARDOUR_UI::check_memory_locking ()
690 {
691 #ifdef __APPLE__
692         /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
693         return;
694 #else // !__APPLE__
695
696         XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"));
697
698         if (engine->is_realtime() && memory_warning_node == 0) {
699
700                 struct rlimit limits;
701                 int64_t ram;
702                 long pages, page_size;
703
704                 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
705                         ram = 0;
706                 } else {
707                         ram = (int64_t) pages * (int64_t) page_size;
708                 }
709
710                 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
711                         return;
712                 }
713
714                 if (limits.rlim_cur != RLIM_INFINITY) {
715
716                         if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
717
718
719                                 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
720                                                      "This might cause Ardour to run out of memory before your system "
721                                                      "runs out of memory. \n\n"
722                                                      "You can view the memory limit with 'ulimit -l', "
723                                                      "and it is normally controlled by /etc/security/limits.conf"));
724
725                                 VBox* vbox = msg.get_vbox();
726                                 HBox hbox;
727                                 CheckButton cb (_("Do not show this window again"));
728
729                                 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
730
731                                 hbox.pack_start (cb, true, false);
732                                 vbox->pack_start (hbox);
733                                 cb.show();
734                                 vbox->show();
735                                 hbox.show ();
736
737                                 pop_back_splash ();
738
739                                 editor->ensure_float (msg);
740                                 msg.run ();
741                         }
742                 }
743         }
744 #endif // !__APPLE__
745 }
746
747
748 void
749 ARDOUR_UI::finish()
750 {
751         if (session) {
752
753                 if (session->transport_rolling()) {
754                         session->request_stop ();
755                         usleep (250000);
756                 }
757
758                 if (session->dirty()) {
759                         switch (ask_about_saving_session(_("quit"))) {
760                         case -1:
761                                 return;
762                                 break;
763                         case 1:
764                                 /* use the default name */
765                                 if (save_state_canfail ("")) {
766                                         /* failed - don't quit */
767                                         MessageDialog msg (*editor,
768                                                            _("\
769 Ardour was unable to save your session.\n\n\
770 If you still wish to quit, please use the\n\n\
771 \"Just quit\" option."));
772                                         pop_back_splash();
773                                         msg.run ();
774                                         return;
775                                 }
776                                 break;
777                         case 0:
778                                 break;
779                         }
780                 }
781
782                 second_connection.disconnect ();
783                 point_one_second_connection.disconnect ();
784                 point_oh_five_second_connection.disconnect ();
785                 point_zero_one_second_connection.disconnect();
786                 
787                 // session->set_deletion_in_progress ();
788                 session->remove_pending_capture_state ();
789                 delete session;
790                 session = 0;
791         }
792
793         ArdourDialog::close_all_dialogs ();
794         engine->stop (true);
795         save_ardour_state ();
796         quit ();
797 }
798
799 int
800 ARDOUR_UI::ask_about_saving_session (const string & what)
801 {
802         ArdourDialog window (_("ardour: save session?"));
803         Gtk::HBox dhbox;  // the hbox for the image and text
804         Gtk::Label  prompt_label;
805         Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING,  Gtk::ICON_SIZE_DIALOG));
806
807         string msg;
808
809         msg = string_compose(_("Don't %1"), what);
810         window.add_button (msg, RESPONSE_REJECT);
811         msg = string_compose(_("Just %1"), what);
812         window.add_button (msg, RESPONSE_APPLY);
813         msg = string_compose(_("Save and %1"), what);
814         window.add_button (msg, RESPONSE_ACCEPT);
815
816         window.set_default_response (RESPONSE_ACCEPT);
817
818         Gtk::Button noquit_button (msg);
819         noquit_button.set_name ("EditorGTKButton");
820
821         string prompt;
822         string type;
823
824         if (session->snap_name() == session->name()) {
825                 type = _("session");
826         } else {
827                 type = _("snapshot");
828         }
829         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?"),
830                          type, session->snap_name());
831
832         prompt_label.set_text (prompt);
833         prompt_label.set_name (X_("PrompterLabel"));
834         prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
835
836         dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP);
837         dhbox.set_homogeneous (false);
838         dhbox.pack_start (*dimage, false, false, 5);
839         dhbox.pack_start (prompt_label, true, false, 5);
840         window.get_vbox()->pack_start (dhbox);
841
842         window.set_name (_("Prompter"));
843         window.set_position (Gtk::WIN_POS_MOUSE);
844         window.set_modal (true);
845         window.set_resizable (false);
846
847         dhbox.show();
848         prompt_label.show();
849         dimage->show();
850         window.show();
851         window.set_keep_above (true);
852         window.present ();
853
854         ResponseType r = (ResponseType) window.run();
855
856         window.hide ();
857
858         switch (r) {
859         case RESPONSE_ACCEPT: // save and get out of here
860                 return 1;
861         case RESPONSE_APPLY:  // get out of here
862                 return 0;
863         default:
864                 break;
865         }
866
867         return -1;
868 }
869
870 gint
871 ARDOUR_UI::every_second ()
872 {
873         update_cpu_load ();
874         update_buffer_load ();
875         update_disk_space ();
876         return TRUE;
877 }
878
879 gint
880 ARDOUR_UI::every_point_one_seconds ()
881 {
882         update_speed_display ();
883         RapidScreenUpdate(); /* EMIT_SIGNAL */
884         return TRUE;
885 }
886
887 gint
888 ARDOUR_UI::every_point_zero_one_seconds ()
889 {
890         // august 2007: actual update frequency: 40Hz, not 100Hz
891
892         SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
893         return TRUE;
894 }
895
896 void
897 ARDOUR_UI::update_sample_rate (nframes_t ignored)
898 {
899         char buf[32];
900
901         ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
902
903         if (!engine->connected()) {
904
905                 snprintf (buf, sizeof (buf), _("disconnected"));
906
907         } else {
908
909                 nframes_t rate = engine->frame_rate();
910
911                 if (fmod (rate, 1000.0) != 0.0) {
912                         snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
913                                   (float) rate/1000.0f,
914                                   (engine->frames_per_cycle() / (float) rate) * 1000.0f);
915                 } else {
916                         snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
917                                   rate/1000,
918                                   (engine->frames_per_cycle() / (float) rate) * 1000.0f);
919                 }
920         }
921
922         sample_rate_label.set_text (buf);
923 }
924
925 void
926 ARDOUR_UI::update_cpu_load ()
927 {
928         char buf[32];
929         snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
930         cpu_load_label.set_text (buf);
931 }
932
933 void
934 ARDOUR_UI::update_buffer_load ()
935 {
936         char buf[64];
937         uint32_t c, p;
938
939         if (session) {
940                 c = session->capture_load ();
941                 p = session->playback_load ();
942
943                 push_buffer_stats (c, p);
944
945                 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
946                           session->playback_load(), session->capture_load());
947                 buffer_load_label.set_text (buf);
948         } else {
949                 buffer_load_label.set_text ("");
950         }
951 }
952
953 void
954 ARDOUR_UI::count_recenabled_streams (Route& route)
955 {
956         Track* track = dynamic_cast<Track*>(&route);
957         if (track && track->diskstream()->record_enabled()) {
958                 rec_enabled_streams += track->n_inputs().n_total();
959         }
960 }
961
962 void
963 ARDOUR_UI::update_disk_space()
964 {
965         if (session == 0) {
966                 return;
967         }
968
969         nframes_t frames = session->available_capture_duration();
970         char buf[64];
971         nframes_t fr = session->frame_rate();
972
973         if (frames == max_frames) {
974                 strcpy (buf, _("Disk: 24hrs+"));
975         } else {
976                 rec_enabled_streams = 0;
977                 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
978
979                 if (rec_enabled_streams) {
980                         frames /= rec_enabled_streams;
981                 }
982
983                 int hrs;
984                 int mins;
985                 int secs;
986
987                 hrs  = frames / (fr * 3600);
988                 frames -= hrs * fr * 3600;
989                 mins = frames / (fr * 60);
990                 frames -= mins * fr * 60;
991                 secs = frames / fr;
992
993                 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
994         }
995
996         disk_space_label.set_text (buf);
997
998         // An attempt to make the disk space label flash red when space has run out.
999
1000         if (frames < fr * 60 * 5) {
1001         /*      disk_space_box.style ("disk_space_label_empty"); */
1002         } else {
1003         /*      disk_space_box.style ("disk_space_label"); */
1004         }
1005
1006 }
1007
1008 gint
1009 ARDOUR_UI::update_wall_clock ()
1010 {
1011         time_t now;
1012         struct tm *tm_now;
1013         char buf[16];
1014
1015         time (&now);
1016         tm_now = localtime (&now);
1017
1018         sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
1019         wall_clock_label.set_text (buf);
1020
1021         return TRUE;
1022 }
1023
1024 gint
1025 ARDOUR_UI::session_menu (GdkEventButton */*ev*/)
1026 {
1027         session_popup_menu->popup (0, 0);
1028         return TRUE;
1029 }
1030
1031 void
1032 ARDOUR_UI::redisplay_recent_sessions ()
1033 {
1034         std::vector<sys::path> session_directories;
1035         RecentSessionsSorter cmp;
1036
1037         recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
1038         recent_session_model->clear ();
1039
1040         ARDOUR::RecentSessions rs;
1041         ARDOUR::read_recent_sessions (rs);
1042
1043         if (rs.empty()) {
1044                 recent_session_display.set_model (recent_session_model);
1045                 return;
1046         }
1047         //
1048         // sort them alphabetically
1049         sort (rs.begin(), rs.end(), cmp);
1050
1051         for (ARDOUR::RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1052                 session_directories.push_back ((*i).second);
1053         }
1054
1055         for (vector<sys::path>::const_iterator i = session_directories.begin();
1056                         i != session_directories.end(); ++i)
1057         {
1058                 std::vector<sys::path> state_file_paths;
1059
1060                 // now get available states for this session
1061
1062                 get_state_files_in_directory (*i, state_file_paths);
1063
1064                 vector<string*>* states;
1065                 vector<const gchar*> item;
1066                 string fullpath = (*i).to_string();
1067
1068                 /* remove any trailing / */
1069
1070                 if (fullpath[fullpath.length()-1] == '/') {
1071                         fullpath = fullpath.substr (0, fullpath.length()-1);
1072                 }
1073
1074                 /* check whether session still exists */
1075                 if (!Glib::file_test(fullpath.c_str(), Glib::FILE_TEST_EXISTS)) {
1076                         /* session doesn't exist */
1077                         cerr << "skipping non-existent session " << fullpath << endl;
1078                         continue;
1079                 }
1080
1081                 /* now get available states for this session */
1082
1083                 if ((states = Session::possible_states (fullpath)) == 0) {
1084                         /* no state file? */
1085                         continue;
1086                 }
1087
1088                 std::vector<string> state_file_names(get_file_names_no_extension (state_file_paths));
1089
1090                 Gtk::TreeModel::Row row = *(recent_session_model->append());
1091
1092                 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1093                 row[recent_session_columns.fullpath] = fullpath;
1094
1095                 if (state_file_names.size() > 1) {
1096
1097                         // add the children
1098
1099                         for (std::vector<std::string>::iterator i2 = state_file_names.begin();
1100                                         i2 != state_file_names.end(); ++i2)
1101                         {
1102
1103                                 Gtk::TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1104
1105                                 child_row[recent_session_columns.visible_name] = *i2;
1106                                 child_row[recent_session_columns.fullpath] = fullpath;
1107                         }
1108                 }
1109         }
1110
1111         recent_session_display.set_model (recent_session_model);
1112 }
1113
1114 void
1115 ARDOUR_UI::build_session_selector ()
1116 {
1117         session_selector_window = new ArdourDialog (_("Recent Sessions"));
1118
1119         Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1120
1121         session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1122         session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1123         session_selector_window->set_default_response (RESPONSE_ACCEPT);
1124         recent_session_model = TreeStore::create (recent_session_columns);
1125         recent_session_display.set_model (recent_session_model);
1126         recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1127         recent_session_display.set_headers_visible (false);
1128         recent_session_display.get_selection()->set_mode (SELECTION_BROWSE);
1129         recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1130
1131         scroller->add (recent_session_display);
1132         scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1133
1134         session_selector_window->set_name ("SessionSelectorWindow");
1135         session_selector_window->set_size_request (200, 400);
1136         session_selector_window->get_vbox()->pack_start (*scroller);
1137
1138         recent_session_display.show();
1139         scroller->show();
1140         //session_selector_window->get_vbox()->show();
1141 }
1142
1143 void
1144 ARDOUR_UI::recent_session_row_activated (const TreePath& /*path*/, TreeViewColumn* /*col*/)
1145 {
1146         session_selector_window->response (RESPONSE_ACCEPT);
1147 }
1148
1149 void
1150 ARDOUR_UI::open_recent_session ()
1151 {
1152         bool can_return = (session != 0);
1153
1154         if (session_selector_window == 0) {
1155                 build_session_selector ();
1156         }
1157
1158         redisplay_recent_sessions ();
1159
1160         while (true) {
1161
1162                 session_selector_window->set_position (WIN_POS_MOUSE);
1163
1164                 ResponseType r = (ResponseType) session_selector_window->run ();
1165
1166                 switch (r) {
1167                 case RESPONSE_ACCEPT:
1168                         break;
1169                 default:
1170                         if (can_return) {
1171                                 session_selector_window->hide();
1172                                 return;
1173                         } else {
1174                                 exit (1);
1175                         }
1176                 }
1177
1178                 if (recent_session_display.get_selection()->count_selected_rows() == 0) {
1179                         continue;
1180                 }
1181
1182                 session_selector_window->hide();
1183
1184                 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1185
1186                 if (i == recent_session_model->children().end()) {
1187                         return;
1188                 }
1189
1190                 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1191                 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1192
1193                 _session_is_new = false;
1194
1195                 if (load_session (path, state) == 0) {
1196                         break;
1197                 }
1198
1199                 can_return = false;
1200         }
1201 }
1202
1203 bool
1204 ARDOUR_UI::check_audioengine ()
1205 {
1206         if (engine) {
1207                 if (!engine->connected()) {
1208                         MessageDialog msg (_("Ardour is not connected to JACK\n"
1209                                              "You cannot open or close sessions in this condition"));
1210                         pop_back_splash ();
1211                         msg.run ();
1212                         return false;
1213                 }
1214                 return true;
1215         } else {
1216                 return false;
1217         }
1218 }
1219
1220 void
1221 ARDOUR_UI::open_session ()
1222 {
1223         if (!check_audioengine()) {
1224                 return;
1225
1226         }
1227
1228         /* popup selector window */
1229
1230         if (open_session_selector == 0) {
1231
1232                 /* ardour sessions are folders */
1233
1234                 open_session_selector = new Gtk::FileChooserDialog (_("Open Session"), FILE_CHOOSER_ACTION_OPEN);
1235                 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1236                 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1237                 open_session_selector->set_default_response(Gtk::RESPONSE_ACCEPT);
1238
1239                 FileFilter session_filter;
1240                 session_filter.add_pattern ("*.ardour");
1241                 session_filter.set_name (_("Ardour sessions"));
1242                 open_session_selector->add_filter (session_filter);
1243                 open_session_selector->set_filter (session_filter);
1244         }
1245
1246         int response = open_session_selector->run();
1247         open_session_selector->hide ();
1248
1249         switch (response) {
1250         case RESPONSE_ACCEPT:
1251                 break;
1252         default:
1253                 open_session_selector->hide();
1254                 return;
1255         }
1256
1257         open_session_selector->hide();
1258         string session_path = open_session_selector->get_filename();
1259         string path, name;
1260         bool isnew;
1261
1262         if (session_path.length() > 0) {
1263                 if (ARDOUR::find_session (session_path, path, name, isnew) == 0) {
1264                         _session_is_new = isnew;
1265                         load_session (path, name);
1266                 }
1267         }
1268 }
1269
1270
1271 void
1272 ARDOUR_UI::session_add_midi_route (bool disk, RouteGroup* route_group, uint32_t how_many)
1273 {
1274         list<boost::shared_ptr<MidiTrack> > tracks;
1275
1276         if (session == 0) {
1277                 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1278                 return;
1279         }
1280
1281         try {
1282                 if (disk) {
1283
1284                         tracks = session->new_midi_track (ARDOUR::Normal, route_group, how_many);
1285
1286                         if (tracks.size() != how_many) {
1287                                 if (how_many == 1) {
1288                                         error << _("could not create a new midi track") << endmsg;
1289                                 } else {
1290                                         error << string_compose (_("could not create %1 new midi tracks"), how_many) << endmsg;
1291                                 }
1292                         }
1293                 } /*else {
1294                         if ((route = session->new_midi_route ()) == 0) {
1295                                 error << _("could not create new midi bus") << endmsg;
1296                         }
1297                 }*/
1298         }
1299
1300         catch (...) {
1301                 MessageDialog msg (*editor,
1302                                    _("There are insufficient JACK ports available\n\
1303 to create a new track or bus.\n\
1304 You should save Ardour, exit and\n\
1305 restart JACK with more ports."));
1306                 msg.run ();
1307         }
1308 }
1309
1310
1311 void
1312 ARDOUR_UI::session_add_audio_route (bool track, bool aux, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, RouteGroup* route_group, uint32_t how_many)
1313 {
1314         list<boost::shared_ptr<AudioTrack> > tracks;
1315         RouteList routes;
1316
1317         if (session == 0) {
1318                 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1319                 return;
1320         }
1321
1322         try {
1323                 if (track) {
1324                         tracks = session->new_audio_track (input_channels, output_channels, mode, route_group, how_many);
1325
1326                         if (tracks.size() != how_many) {
1327                                 if (how_many == 1) {
1328                                         error << _("could not create a new audio track") << endmsg;
1329                                 } else {
1330                                         error << string_compose (_("could only create %1 of %2 new audio %3"),
1331                                                                  tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1332                                 }
1333                         }
1334
1335                 } else {
1336
1337                         routes = session->new_audio_route (aux, input_channels, output_channels, route_group, how_many);
1338
1339                         if (routes.size() != how_many) {
1340                                 if (how_many == 1) {
1341                                         error << _("could not create a new audio track") << endmsg;
1342                                 } else {
1343                                         error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1344                                 }
1345                         }
1346                 }
1347
1348 #if CONTROLOUTS
1349                 if (need_control_room_outs) {
1350                         pan_t pans[2];
1351
1352                         pans[0] = 0.5;
1353                         pans[1] = 0.5;
1354
1355                         route->set_stereo_control_outs (control_lr_channels);
1356                         route->control_outs()->set_stereo_pan (pans, this);
1357                 }
1358 #endif /* CONTROLOUTS */
1359         }
1360
1361         catch (...) {
1362                 MessageDialog msg (*editor,
1363                                    _("There are insufficient JACK ports available\n\
1364 to create a new track or bus.\n\
1365 You should save Ardour, exit and\n\
1366 restart JACK with more ports."));
1367                 pop_back_splash ();
1368                 msg.run ();
1369         }
1370 }
1371
1372 void
1373 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1374 {
1375         nframes_t _preroll = 0;
1376
1377         if (session) {
1378                 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1379                 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1380
1381                 if (new_position > _preroll) {
1382                         new_position -= _preroll;
1383                 } else {
1384                         new_position = 0;
1385                 }
1386
1387                 session->request_locate (new_position);
1388         }
1389 }
1390
1391 void
1392 ARDOUR_UI::transport_goto_start ()
1393 {
1394         if (session) {
1395                 session->goto_start();
1396
1397                 /* force displayed area in editor to start no matter
1398                    what "follow playhead" setting is.
1399                 */
1400
1401                 if (editor) {
1402                         editor->center_screen (session->current_start_frame ());
1403                 }
1404         }
1405 }
1406
1407 void
1408 ARDOUR_UI::transport_goto_zero ()
1409 {
1410         if (session) {
1411                 session->request_locate (0);
1412
1413
1414                 /* force displayed area in editor to start no matter
1415                    what "follow playhead" setting is.
1416                 */
1417
1418                 if (editor) {
1419                         editor->reset_x_origin (0);
1420                 }
1421         }
1422 }
1423
1424 void
1425 ARDOUR_UI::transport_goto_wallclock ()
1426 {
1427         if (session && editor) {
1428
1429                 time_t now;
1430                 struct tm tmnow;
1431                 nframes64_t frames;
1432
1433                 time (&now);
1434                 localtime_r (&now, &tmnow);
1435
1436                 frames = tmnow.tm_hour * (60 * 60 * session->frame_rate());
1437                 frames += tmnow.tm_min * (60 * session->frame_rate());
1438                 frames += tmnow.tm_sec * session->frame_rate();
1439
1440                 session->request_locate (frames);
1441
1442                 /* force displayed area in editor to start no matter
1443                    what "follow playhead" setting is.
1444                 */
1445
1446                 if (editor) {
1447                         editor->center_screen (frames);
1448                 }
1449         }
1450 }
1451
1452 void
1453 ARDOUR_UI::transport_goto_end ()
1454 {
1455         if (session) {
1456                 nframes_t const frame = session->current_end_frame();
1457                 session->request_locate (frame);
1458
1459                 /* force displayed area in editor to start no matter
1460                    what "follow playhead" setting is.
1461                 */
1462
1463                 if (editor) {
1464                         editor->center_screen (frame);
1465                 }
1466         }
1467 }
1468
1469 void
1470 ARDOUR_UI::transport_stop ()
1471 {
1472         if (!session) {
1473                 return;
1474         }
1475
1476         if (session->is_auditioning()) {
1477                 session->cancel_audition ();
1478                 return;
1479         }
1480
1481         session->request_stop ();
1482 }
1483
1484 void
1485 ARDOUR_UI::transport_stop_and_forget_capture ()
1486 {
1487         if (session) {
1488                 session->request_stop (true);
1489         }
1490 }
1491
1492 void
1493 ARDOUR_UI::remove_last_capture()
1494 {
1495         if (editor) {
1496                 editor->remove_last_capture();
1497         }
1498 }
1499
1500 void
1501 ARDOUR_UI::transport_record (bool roll)
1502 {
1503
1504         if (session) {
1505                 switch (session->record_status()) {
1506                 case Session::Disabled:
1507                         if (session->ntracks() == 0) {
1508                                 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1509                                 msg.run ();
1510                                 return;
1511                         }
1512                         session->maybe_enable_record ();
1513                         if (roll) {
1514                                 transport_roll ();
1515                         }
1516                         break;
1517                 case Session::Recording:
1518                         if (roll) {
1519                                 session->request_stop();
1520                         } else {
1521                                 session->disable_record (false, true);
1522                         }
1523                         break;
1524
1525                 case Session::Enabled:
1526                         session->disable_record (false, true);
1527                 }
1528         }
1529         //cerr << "ARDOUR_UI::transport_record () called roll = " << roll << " session->record_status() = " << session->record_status() << endl;
1530 }
1531
1532 void 
1533 ARDOUR_UI::transport_roll ()
1534 {
1535         if (!session) {
1536                 return;
1537         }
1538
1539         if (session->is_auditioning()) {
1540                 return;
1541         }
1542         
1543         if (session->config.get_external_sync()) {
1544                 switch (session->config.get_sync_source()) {
1545                 case JACK:
1546                         break;
1547                 default:
1548                         /* transport controlled by the master */
1549                         return;
1550                 }
1551         }
1552
1553         bool rolling = session->transport_rolling();
1554
1555         if (session->get_play_loop()) {
1556                 session->request_play_loop (false, true);
1557         } else if (session->get_play_range ()) {
1558                 session->request_play_range (false, true);
1559         } 
1560
1561         if (!rolling) {
1562                 session->request_transport_speed (1.0f);
1563         }
1564
1565         map_transport_state ();
1566 }
1567
1568 void
1569 ARDOUR_UI::toggle_roll (bool with_abort, bool roll_out_of_bounded_mode)
1570 {
1571         
1572         if (!session) {
1573                 return;
1574         }
1575
1576         if (session->is_auditioning()) {
1577                 session->cancel_audition ();
1578                 return;
1579         }
1580         
1581         if (session->config.get_external_sync()) {
1582                 switch (session->config.get_sync_source()) {
1583                 case JACK:
1584                         break;
1585                 default:
1586                         /* transport controlled by the master */
1587                         return;
1588                 }
1589         }
1590
1591         bool rolling = session->transport_rolling();
1592         bool affect_transport = true;
1593
1594         if (rolling && roll_out_of_bounded_mode) {
1595                 /* drop out of loop/range playback but leave transport rolling */
1596                 if (session->get_play_loop()) {
1597                         if (Config->get_seamless_loop()) {
1598                                 /* the disk buffers contain copies of the loop - we can't 
1599                                    just keep playing, so stop the transport. the user
1600                                    can restart as they wish.
1601                                 */
1602                                 affect_transport = true;
1603                         } else {
1604                                 /* disk buffers are normal, so we can keep playing */
1605                                 affect_transport = false;
1606                         }
1607                         session->request_play_loop (false, true);
1608                 } else if (session->get_play_range ()) {
1609                         affect_transport = false;
1610                         session->request_play_range (0, true);
1611                 } 
1612         } 
1613
1614         if (affect_transport) {
1615                 if (rolling) {
1616                         session->request_stop (with_abort, true);
1617                 } else {
1618                         session->request_transport_speed (1.0f);
1619                 }
1620         }
1621
1622         map_transport_state (); 
1623 }
1624
1625 void
1626 ARDOUR_UI::toggle_session_auto_loop ()
1627 {
1628         if (session) {
1629                 if (session->get_play_loop()) {
1630                         if (session->transport_rolling()) {
1631                                 Location * looploc = session->locations()->auto_loop_location();
1632                                 if (looploc) {
1633                                         session->request_locate (looploc->start(), true);
1634                                 }
1635                         } else {
1636                                 session->request_play_loop (false);
1637                         }
1638                 } else {
1639                         Location * looploc = session->locations()->auto_loop_location();
1640                         if (looploc) {
1641                                 session->request_play_loop (true);
1642                         }
1643                 }
1644         }
1645 }
1646
1647 void
1648 ARDOUR_UI::transport_play_selection ()
1649 {
1650         if (!session) {
1651                 return;
1652         }
1653
1654         editor->play_selection ();
1655 }
1656
1657 void
1658 ARDOUR_UI::transport_rewind (int option)
1659 {
1660         float current_transport_speed;
1661
1662         if (session) {
1663                 current_transport_speed = session->transport_speed();
1664
1665                 if (current_transport_speed >= 0.0f) {
1666                         switch (option) {
1667                         case 0:
1668                                 session->request_transport_speed (-1.0f);
1669                                 break;
1670                         case 1:
1671                                 session->request_transport_speed (-4.0f);
1672                                 break;
1673                         case -1:
1674                                 session->request_transport_speed (-0.5f);
1675                                 break;
1676                         }
1677                 } else {
1678                         /* speed up */
1679                         session->request_transport_speed (current_transport_speed * 1.5f);
1680                 }
1681         }
1682 }
1683
1684 void
1685 ARDOUR_UI::transport_forward (int option)
1686 {
1687         float current_transport_speed;
1688
1689         if (session) {
1690                 current_transport_speed = session->transport_speed();
1691
1692                 if (current_transport_speed <= 0.0f) {
1693                         switch (option) {
1694                         case 0:
1695                                 session->request_transport_speed (1.0f);
1696                                 break;
1697                         case 1:
1698                                 session->request_transport_speed (4.0f);
1699                                 break;
1700                         case -1:
1701                                 session->request_transport_speed (0.5f);
1702                                 break;
1703                         }
1704                 } else {
1705                         /* speed up */
1706                         session->request_transport_speed (current_transport_speed * 1.5f);
1707                 }
1708
1709         }
1710 }
1711
1712 void
1713 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1714 {
1715         if (session == 0) {
1716                 return;
1717         }
1718
1719         boost::shared_ptr<Route> r;
1720
1721         if ((r = session->route_by_remote_id (dstream)) != 0) {
1722
1723                 Track* t;
1724
1725                 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1726                         t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1727                 }
1728         }
1729         if (session == 0) {
1730                 return;
1731         }
1732 }
1733
1734 void
1735 ARDOUR_UI::map_transport_state ()
1736 {
1737         ENSURE_GUI_THREAD(mem_fun (*this, &ARDOUR_UI::map_transport_state));
1738
1739         if (!session) {
1740                 auto_loop_button.set_visual_state (0);
1741                 play_selection_button.set_visual_state (0);
1742                 roll_button.set_visual_state (0);
1743                 stop_button.set_visual_state (1);
1744                 return;
1745         }
1746
1747         float sp = session->transport_speed();
1748
1749         if (sp == 1.0f) {
1750                 shuttle_fract = SHUTTLE_FRACT_SPEED1;  /* speed = 1.0, believe it or not */
1751                 shuttle_box.queue_draw ();
1752         } else if (sp == 0.0f) {
1753                 shuttle_fract = 0;
1754                 shuttle_box.queue_draw ();
1755                 update_disk_space ();
1756         }
1757
1758         if (sp != 0.0) {
1759
1760                 if (session->get_play_range()) {
1761
1762                         play_selection_button.set_visual_state (1);
1763                         roll_button.set_visual_state (0);
1764                         auto_loop_button.set_visual_state (0);
1765                         
1766                 } else if (session->get_play_loop ()) {
1767                         
1768                         auto_loop_button.set_visual_state (1);
1769                         play_selection_button.set_visual_state (0);
1770                         roll_button.set_visual_state (0);
1771
1772                 } else {
1773                         
1774                         roll_button.set_visual_state (1);
1775                         play_selection_button.set_visual_state (0);
1776                         auto_loop_button.set_visual_state (0);
1777                 }
1778
1779                 stop_button.set_visual_state (0);
1780
1781         } else {
1782
1783                 stop_button.set_visual_state (1);
1784                 roll_button.set_visual_state (0);
1785                 play_selection_button.set_visual_state (0);
1786                 auto_loop_button.set_visual_state (0);
1787         }
1788
1789 }
1790
1791 void
1792 ARDOUR_UI::engine_stopped ()
1793 {
1794         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1795         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1796         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1797 }
1798
1799 void
1800 ARDOUR_UI::engine_running ()
1801 {
1802         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1803         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1804         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1805
1806         Glib::RefPtr<Action> action;
1807         const char* action_name = 0;
1808
1809         switch (engine->frames_per_cycle()) {
1810         case 32:
1811                 action_name = X_("JACKLatency32");
1812                 break;
1813         case 64:
1814                 action_name = X_("JACKLatency64");
1815                 break;
1816         case 128:
1817                 action_name = X_("JACKLatency128");
1818                 break;
1819         case 512:
1820                 action_name = X_("JACKLatency512");
1821                 break;
1822         case 1024:
1823                 action_name = X_("JACKLatency1024");
1824                 break;
1825         case 2048:
1826                 action_name = X_("JACKLatency2048");
1827                 break;
1828         case 4096:
1829                 action_name = X_("JACKLatency4096");
1830                 break;
1831         case 8192:
1832                 action_name = X_("JACKLatency8192");
1833                 break;
1834         default:
1835                 /* XXX can we do anything useful ? */
1836                 break;
1837         }
1838
1839         if (action_name) {
1840
1841                 action = ActionManager::get_action (X_("JACK"), action_name);
1842
1843                 if (action) {
1844                         Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1845                         ract->set_active ();
1846                 }
1847         }
1848 }
1849
1850 void
1851 ARDOUR_UI::engine_halted ()
1852 {
1853         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1854
1855         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1856         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1857
1858         update_sample_rate (0);
1859
1860         MessageDialog msg (*editor,
1861                            _("\
1862 JACK has either been shutdown or it\n\
1863 disconnected Ardour because Ardour\n\
1864 was not fast enough. Try to restart\n\
1865 JACK, reconnect and save the session."));
1866         pop_back_splash ();
1867         msg.run ();
1868 }
1869
1870 int32_t
1871 ARDOUR_UI::do_engine_start ()
1872 {
1873         try {
1874                 engine->start();
1875         }
1876
1877         catch (...) {
1878                 engine->stop ();
1879                 error << _("Unable to start the session running")
1880                       << endmsg;
1881                 unload_session ();
1882                 return -2;
1883         }
1884
1885         return 0;
1886 }
1887
1888 void
1889 ARDOUR_UI::setup_theme ()
1890 {
1891         theme_manager->setup_theme();
1892 }
1893
1894 void
1895 ARDOUR_UI::update_clocks ()
1896 {
1897         if (!editor || !editor->dragging_playhead()) {
1898                 Clock (session->audible_frame(), false, editor->get_preferred_edit_position()); /* EMIT_SIGNAL */
1899         }
1900 }
1901
1902 void
1903 ARDOUR_UI::start_clocking ()
1904 {
1905         clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1906 }
1907
1908 void
1909 ARDOUR_UI::stop_clocking ()
1910 {
1911         clock_signal_connection.disconnect ();
1912 }
1913
1914 void
1915 ARDOUR_UI::toggle_clocking ()
1916 {
1917 #if 0
1918         if (clock_button.get_active()) {
1919                 start_clocking ();
1920         } else {
1921                 stop_clocking ();
1922         }
1923 #endif
1924 }
1925
1926 gint
1927 ARDOUR_UI::_blink (void *arg)
1928
1929 {
1930         ((ARDOUR_UI *) arg)->blink ();
1931         return TRUE;
1932 }
1933
1934 void
1935 ARDOUR_UI::blink ()
1936 {
1937         Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1938 }
1939
1940 void
1941 ARDOUR_UI::start_blinking ()
1942 {
1943         /* Start the blink signal. Everybody with a blinking widget
1944            uses Blink to drive the widget's state.
1945         */
1946
1947         if (blink_timeout_tag < 0) {
1948                 blink_on = false;
1949                 blink_timeout_tag = g_timeout_add (240, _blink, this);
1950         }
1951 }
1952
1953 void
1954 ARDOUR_UI::stop_blinking ()
1955 {
1956         if (blink_timeout_tag >= 0) {
1957                 g_source_remove (blink_timeout_tag);
1958                 blink_timeout_tag = -1;
1959         }
1960 }
1961
1962
1963 /** Ask the user for the name of a new shapshot and then take it.
1964  */
1965 void
1966 ARDOUR_UI::snapshot_session ()
1967 {
1968         ArdourPrompter prompter (true);
1969         string snapname;
1970         char timebuf[128];
1971         time_t n;
1972         struct tm local_time;
1973
1974         time (&n);
1975         localtime_r (&n, &local_time);
1976         strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1977
1978         prompter.set_name ("Prompter");
1979         prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1980         prompter.set_title (_("Take Snapshot"));
1981         prompter.set_prompt (_("Name of New Snapshot"));
1982         prompter.set_initial_text (timebuf);
1983
1984         switch (prompter.run()) {
1985         case RESPONSE_ACCEPT:
1986         {
1987                 prompter.get_result (snapname);
1988
1989                 bool do_save = (snapname.length() != 0);
1990
1991                 vector<sys::path> p;
1992                 get_state_files_in_directory (session->session_directory().root_path(), p);
1993                 vector<string> n = get_file_names_no_extension (p);
1994                 if (find (n.begin(), n.end(), snapname) != n.end()) {
1995
1996                         ArdourDialog confirm (_("Confirm snapshot overwrite"), true);
1997                         Label m (_("A snapshot already exists with that name.  Do you want to overwrite it?"));
1998                         confirm.get_vbox()->pack_start (m, true, true);
1999                         confirm.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
2000                         confirm.add_button (_("Overwrite"), Gtk::RESPONSE_ACCEPT);
2001                         confirm.show_all ();
2002                         switch (confirm.run()) {
2003                         case RESPONSE_CANCEL:
2004                                 do_save = false;
2005                         }
2006                 }
2007
2008                 if (do_save) {
2009                         save_state (snapname);
2010                 }
2011                 break;
2012         }
2013
2014         default:
2015                 break;
2016         }
2017 }
2018
2019 void
2020 ARDOUR_UI::save_state (const string & name)
2021 {
2022         (void) save_state_canfail (name);
2023 }
2024
2025 int
2026 ARDOUR_UI::save_state_canfail (string name)
2027 {
2028         if (session) {
2029                 int ret;
2030
2031                 if (name.length() == 0) {
2032                         name = session->snap_name();
2033                 }
2034
2035                 if ((ret = session->save_state (name)) != 0) {
2036                         return ret;
2037                 }
2038         }
2039         save_ardour_state (); /* XXX cannot fail? yeah, right ... */
2040         return 0;
2041 }
2042
2043 void
2044 ARDOUR_UI::primary_clock_value_changed ()
2045 {
2046         if (session) {
2047                 session->request_locate (primary_clock.current_time ());
2048         }
2049 }
2050
2051 void
2052 ARDOUR_UI::big_clock_value_changed ()
2053 {
2054         if (session) {
2055                 session->request_locate (big_clock.current_time ());
2056         }
2057 }
2058
2059 void
2060 ARDOUR_UI::secondary_clock_value_changed ()
2061 {
2062         if (session) {
2063                 session->request_locate (secondary_clock.current_time ());
2064         }
2065 }
2066
2067 void
2068 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
2069 {
2070         if (session == 0) {
2071                 return;
2072         }
2073
2074         Session::RecordState const r = session->record_status ();
2075         bool const h = session->have_rec_enabled_diskstream ();
2076
2077         if (r == Session::Enabled || (r == Session::Recording && !h)) {
2078                 if (onoff) {
2079                         rec_button.set_visual_state (2);
2080                 } else {
2081                         rec_button.set_visual_state (0);
2082                 }
2083         } else if (r == Session::Recording && h) {
2084                 rec_button.set_visual_state (1);
2085         } else {
2086                 rec_button.set_visual_state (0);
2087         }
2088 }
2089
2090 void
2091 ARDOUR_UI::save_template ()
2092 {
2093         ArdourPrompter prompter (true);
2094         string name;
2095
2096         if (!check_audioengine()) {
2097                 return;
2098         }
2099
2100         prompter.set_name (X_("Prompter"));
2101         prompter.set_title (_("Save Mix Template"));
2102         prompter.set_prompt (_("Name for mix template:"));
2103         prompter.set_initial_text(session->name() + _("-template"));
2104         prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2105
2106         switch (prompter.run()) {
2107         case RESPONSE_ACCEPT:
2108                 prompter.get_result (name);
2109
2110                 if (name.length()) {
2111                         session->save_template (name);
2112                 }
2113                 break;
2114
2115         default:
2116                 break;
2117         }
2118 }
2119
2120 void
2121 ARDOUR_UI::edit_metadata ()
2122 {
2123         SessionMetadataEditor dialog;
2124         dialog.set_session (session);
2125         editor->ensure_float (dialog);
2126         dialog.run ();
2127 }
2128
2129 void
2130 ARDOUR_UI::import_metadata ()
2131 {
2132         SessionMetadataImporter dialog;
2133         dialog.set_session (session);
2134         editor->ensure_float (dialog);
2135         dialog.run ();
2136 }
2137
2138 void
2139 ARDOUR_UI::fontconfig_dialog ()
2140 {
2141 #ifdef GTKOSX
2142         /* X11 users will always have fontconfig info around, but new GTK-OSX users
2143            may not and it can take a while to build it. Warn them.
2144         */
2145
2146         Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
2147
2148         if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
2149                 MessageDialog msg (*_startup,
2150                                    _("Welcome to Ardour.\n\n"
2151                                      "The program will take a bit longer to start up\n"
2152                                      "while the system fonts are checked.\n\n"
2153                                      "This will only be done once, and you will\n"
2154                                      "not see this message again\n"),
2155                                    true,
2156                                    Gtk::MESSAGE_INFO,
2157                                    Gtk::BUTTONS_OK);
2158                 pop_back_splash ();
2159                 msg.show_all ();
2160                 msg.present ();
2161                 msg.run ();
2162         }
2163 #endif
2164 }
2165
2166 void
2167 ARDOUR_UI::parse_cmdline_path (const Glib::ustring& cmdline_path, Glib::ustring& session_name, Glib::ustring& session_path, bool& existing_session)
2168 {
2169         existing_session = false;
2170
2171         if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_DIR)) {
2172                 session_path = cmdline_path;
2173                 existing_session = true;
2174         } else if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_REGULAR)) {
2175                 session_path = Glib::path_get_dirname (string (cmdline_path));
2176                 existing_session = true;
2177         } else {
2178                 /* it doesn't exist, assume the best */
2179                 session_path = Glib::path_get_dirname (string (cmdline_path));
2180         }
2181
2182         session_name = basename_nosuffix (string (cmdline_path));
2183 }
2184
2185 int
2186 ARDOUR_UI::load_cmdline_session (const Glib::ustring& session_name, const Glib::ustring& session_path, bool& existing_session)
2187 {
2188         /* when this is called, the backend audio system must be running */
2189
2190         /* the main idea here is to deal with the fact that a cmdline argument for the session
2191            can be interpreted in different ways - it could be a directory or a file, and before
2192            we load, we need to know both the session directory and the snapshot (statefile) within it
2193            that we are supposed to use.
2194         */
2195
2196         if (session_name.length() == 0 || session_path.length() == 0) {
2197                 return false;
2198         }
2199
2200         if (Glib::file_test (session_path, Glib::FILE_TEST_IS_DIR)) {
2201
2202                 Glib::ustring predicted_session_file;
2203
2204                 predicted_session_file = session_path;
2205                 predicted_session_file += '/';
2206                 predicted_session_file += session_name;
2207                 predicted_session_file += ARDOUR::statefile_suffix;
2208
2209                 if (Glib::file_test (predicted_session_file, Glib::FILE_TEST_EXISTS)) {
2210                         existing_session = true;
2211                 }
2212
2213         } else if (Glib::file_test (session_path, Glib::FILE_TEST_EXISTS)) {
2214
2215                 if (session_path.find (ARDOUR::statefile_suffix) == session_path.length() - 7) {
2216                         /* existing .ardour file */
2217                         existing_session = true;
2218                 }
2219
2220         } else {
2221                 existing_session = false;
2222         }
2223
2224         /* lets just try to load it */
2225
2226         if (create_engine ()) {
2227                 backend_audio_error (false, _startup);
2228                 return -1;
2229         }
2230
2231         return load_session (session_path, session_name);
2232 }
2233
2234 bool
2235 ARDOUR_UI::ask_about_loading_existing_session (const Glib::ustring& session_path)
2236 {
2237         Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2238
2239         MessageDialog msg (str,
2240                            false,
2241                            Gtk::MESSAGE_WARNING,
2242                            Gtk::BUTTONS_YES_NO,
2243                            true);
2244
2245
2246         msg.set_name (X_("OpenExistingDialog"));
2247         msg.set_title (_("Open Existing Session"));
2248         msg.set_wmclass (X_("existing_session"), "Ardour");
2249         msg.set_position (Gtk::WIN_POS_MOUSE);
2250         pop_back_splash ();
2251
2252         switch (msg.run()) {
2253         case RESPONSE_YES:
2254                 return true;
2255                 break;
2256         }
2257         return false;
2258 }
2259
2260 int
2261 ARDOUR_UI::build_session_from_nsd (const Glib::ustring& session_path, const Glib::ustring& session_name)
2262 {
2263
2264         uint32_t cchns;
2265         uint32_t mchns;
2266         AutoConnectOption iconnect;
2267         AutoConnectOption oconnect;
2268         uint32_t nphysin;
2269         uint32_t nphysout;
2270
2271         if (Profile->get_sae()) {
2272
2273                 cchns = 0;
2274                 mchns = 2;
2275                 iconnect = AutoConnectPhysical;
2276                 oconnect = AutoConnectMaster;
2277                 nphysin = 0; // use all available
2278                 nphysout = 0; // use all available
2279
2280         } else {
2281
2282                 /* get settings from advanced section of NSD */
2283
2284                 if (_startup->create_control_bus()) {
2285                         cchns = (uint32_t) _startup->control_channel_count();
2286                 } else {
2287                         cchns = 0;
2288                 }
2289
2290                 if (_startup->create_master_bus()) {
2291                         mchns = (uint32_t) _startup->master_channel_count();
2292                 } else {
2293                         mchns = 0;
2294                 }
2295
2296                 if (_startup->connect_inputs()) {
2297                         iconnect = AutoConnectPhysical;
2298                 } else {
2299                         iconnect = AutoConnectOption (0);
2300                 }
2301
2302                 /// @todo some minor tweaks.
2303
2304                 oconnect = AutoConnectOption (0);
2305
2306                 if (_startup->connect_outputs ()) {
2307                         if (_startup->connect_outs_to_master()) {
2308                                 oconnect = AutoConnectMaster;
2309                         } else if (_startup->connect_outs_to_physical()) {
2310                                 oconnect = AutoConnectPhysical;
2311                         }
2312                 }
2313
2314                 nphysin = (uint32_t) _startup->input_limit_count();
2315                 nphysout = (uint32_t) _startup->output_limit_count();
2316         }
2317
2318         if (build_session (session_path,
2319                            session_name,
2320                            cchns,
2321                            mchns,
2322                            iconnect,
2323                            oconnect,
2324                            nphysin,
2325                            nphysout,
2326                            engine->frame_rate() * 60 * 5)) {
2327
2328                 return -1;
2329         }
2330
2331         return 0;
2332 }
2333
2334 void
2335 ARDOUR_UI::idle_load (const Glib::ustring& path)
2336 {
2337         if (session) {
2338                 if (Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
2339                         /* /path/to/foo => /path/to/foo, foo */
2340                         load_session (path, basename_nosuffix (path));
2341                 } else {
2342                         /* /path/to/foo/foo.ardour => /path/to/foo, foo */
2343                         load_session (Glib::path_get_dirname (path), basename_nosuffix (path));
2344                 }
2345         } else {
2346
2347                 ARDOUR_COMMAND_LINE::session_name = path;
2348
2349                 /*
2350                  * new_session_dialog doens't exist in A3
2351                  * Try to remove all references to it to
2352                  * see if it will compile.  NOTE: this will
2353                  * likely cause a runtime issue is my somewhat
2354                  * uneducated guess.
2355                  */
2356
2357                 //if (new_session_dialog) {
2358
2359
2360                         /* make it break out of Dialog::run() and
2361                            start again.
2362                          */
2363
2364                         //new_session_dialog->response (1);
2365                 //}
2366         }
2367 }
2368
2369 void
2370 ARDOUR_UI::end_loading_messages ()
2371 {
2372         // hide_splash ();
2373 }
2374
2375 void
2376 ARDOUR_UI::loading_message (const std::string& /*msg*/)
2377 {
2378         // show_splash ();
2379         // splash->message (msg);
2380         flush_pending ();
2381 }
2382
2383 /** @param quit_on_cancel true if exit() should be called if the user clicks `cancel' in the new session dialog */
2384 int
2385 ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new)
2386 {
2387         Glib::ustring session_name;
2388         Glib::ustring session_path;
2389         Glib::ustring template_name;
2390         int ret = -1;
2391         bool likely_new = false;
2392
2393         while (ret != 0) {
2394
2395                 if (!should_be_new && !ARDOUR_COMMAND_LINE::session_name.empty()) {
2396
2397                         /* if they named a specific statefile, use it, otherwise they are
2398                            just giving a session folder, and we want to use it as is
2399                            to find the session.
2400                         */
2401
2402                         if (ARDOUR_COMMAND_LINE::session_name.find (statefile_suffix) != string::npos) {
2403                                 session_path = Glib::path_get_dirname (ARDOUR_COMMAND_LINE::session_name);
2404                         } else {
2405                                 session_path = ARDOUR_COMMAND_LINE::session_name;
2406                         }
2407
2408                         session_name = Glib::path_get_basename (ARDOUR_COMMAND_LINE::session_name);
2409
2410                 } else {
2411
2412                         bool const apply = run_startup (should_be_new);
2413                         if (!apply) {
2414                                 if (quit_on_cancel) {
2415                                         exit (1);
2416                                 } else {
2417                                         return ret;
2418                                 }
2419                         }
2420
2421                         /* if we run the startup dialog again, offer more than just "new session" */
2422
2423                         should_be_new = false;
2424
2425                         session_name = _startup->session_name (likely_new);
2426
2427                         /* this shouldn't happen, but we catch it just in case it does */
2428
2429                         if (session_name.empty()) {
2430                                 break;
2431                         }
2432                         if (_startup->use_session_template()) {
2433                                 template_name = _startup->session_template_name();
2434                                 _session_is_new = true;
2435                         }
2436
2437                         if (session_name[0] == '/' ||
2438                             (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2439                             (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2440
2441                                 session_path = Glib::path_get_dirname (session_name);
2442                                 session_name = Glib::path_get_basename (session_name);
2443
2444                         } else {
2445
2446                                 session_path = _startup->session_folder();
2447                         }
2448                 }
2449
2450                 if (create_engine ()) {
2451                         break;
2452                 }
2453
2454                 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2455
2456                         if (likely_new) {
2457
2458                                 Glib::ustring existing = Glib::build_filename (session_path, session_name);
2459
2460                                 if (!ask_about_loading_existing_session (existing)) {
2461                                         ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2462                                         continue;
2463                                 }
2464                         }
2465
2466                         _session_is_new = false;
2467
2468                 } else {
2469
2470                         if (!likely_new) {
2471                                 MessageDialog msg (string_compose (_("There is no existing session at \"%1\""), session_path));
2472                                 msg.run ();
2473                                 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2474                                 continue;
2475                         }
2476
2477                         _session_is_new = true;
2478                 }
2479
2480                 if (likely_new && template_name.empty()) {
2481
2482                         ret = build_session_from_nsd (session_path, session_name);
2483
2484                 } else {
2485
2486                         ret = load_session (session_path, session_name, template_name);
2487                         if (!ARDOUR_COMMAND_LINE::immediate_save.empty()) {
2488                                 session->save_state (ARDOUR_COMMAND_LINE::immediate_save, false);
2489                                 exit (1);
2490                         }
2491                 }
2492         }
2493
2494         return ret;
2495 }
2496
2497 void
2498 ARDOUR_UI::close_session()
2499 {
2500         if (!check_audioengine()) {
2501                 return;
2502         }
2503
2504         unload_session (true);
2505
2506         ARDOUR_COMMAND_LINE::session_name = "";
2507         get_session_parameters (true, false);
2508 }
2509
2510 int
2511 ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_name, Glib::ustring mix_template)
2512 {
2513         Session *new_session;
2514         int unload_status;
2515         int retval = -1;
2516
2517         session_loaded = false;
2518
2519         if (!check_audioengine()) {
2520                 return -1;
2521         }
2522
2523         unload_status = unload_session ();
2524
2525         if (unload_status < 0) {
2526                 goto out;
2527         } else if (unload_status > 0) {
2528                 retval = 0;
2529                 goto out;
2530         }
2531
2532         loading_message (_("Please wait while Ardour loads your session"));
2533
2534         try {
2535                 new_session = new Session (*engine, path, snap_name, mix_template);
2536         }
2537
2538         /* this one is special */
2539
2540         catch (AudioEngine::PortRegistrationFailure& err) {
2541
2542                 MessageDialog msg (err.what(),
2543                                    true,
2544                                    Gtk::MESSAGE_INFO,
2545                                    Gtk::BUTTONS_CLOSE);
2546
2547                 msg.set_title (_("Port Registration Error"));
2548                 msg.set_secondary_text (_("Click the Close button to try again."));
2549                 msg.set_position (Gtk::WIN_POS_CENTER);
2550                 pop_back_splash ();
2551                 msg.present ();
2552
2553                 int response = msg.run ();
2554
2555                 msg.hide ();
2556
2557                 switch (response) {
2558                 case RESPONSE_CANCEL:
2559                         exit (1);
2560                 default:
2561                         break;
2562                 }
2563                 goto out;
2564         }
2565
2566         catch (...) {
2567
2568                 MessageDialog msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name),
2569                                    true,
2570                                    Gtk::MESSAGE_INFO,
2571                                    Gtk::BUTTONS_CLOSE);
2572
2573                 msg.set_title (_("Loading Error"));
2574                 msg.set_secondary_text (_("Click the Close button to try again."));
2575                 msg.set_position (Gtk::WIN_POS_CENTER);
2576                 pop_back_splash ();
2577                 msg.present ();
2578
2579                 int response = msg.run ();
2580
2581                 msg.hide ();
2582
2583                 switch (response) {
2584                 case RESPONSE_CANCEL:
2585                         exit (1);
2586                 default:
2587                         break;
2588                 }
2589                 goto out;
2590         }
2591
2592         connect_to_session (new_session);
2593
2594         session_loaded = true;
2595
2596         goto_editor_window ();
2597
2598         if (session) {
2599                 session->set_clean ();
2600         }
2601
2602         flush_pending ();
2603         retval = 0;
2604
2605   out:
2606         return retval;
2607 }
2608
2609 int
2610 ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_name,
2611                           uint32_t control_channels,
2612                           uint32_t master_channels,
2613                           AutoConnectOption input_connect,
2614                           AutoConnectOption output_connect,
2615                           uint32_t nphysin,
2616                           uint32_t nphysout,
2617                           nframes_t initial_length)
2618 {
2619         Session *new_session;
2620         int x;
2621
2622         if (!check_audioengine()) {
2623                 return -1;
2624         }
2625
2626         session_loaded = false;
2627
2628         x = unload_session ();
2629
2630         if (x < 0) {
2631                 return -1;
2632         } else if (x > 0) {
2633                 return 0;
2634         }
2635
2636         _session_is_new = true;
2637
2638         try {
2639                 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2640                                            control_channels, master_channels, nphysin, nphysout, initial_length);
2641         }
2642
2643         catch (...) {
2644
2645                 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2646                 pop_back_splash ();
2647                 msg.run ();
2648                 return -1;
2649         }
2650
2651         connect_to_session (new_session);
2652
2653         session_loaded = true;
2654
2655         new_session->save_state(new_session->name());
2656
2657         return 0;
2658 }
2659
2660 void
2661 ARDOUR_UI::show ()
2662 {
2663         if (editor) {
2664                 editor->show_window ();
2665
2666                 if (!shown_flag) {
2667                         editor->present ();
2668                 }
2669
2670                 shown_flag = true;
2671         }
2672 }
2673
2674 void
2675 ARDOUR_UI::show_about ()
2676 {
2677         if (about == 0) {
2678                 about = new About;
2679                 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2680         }
2681
2682         about->show_all ();
2683 }
2684
2685 void
2686 ARDOUR_UI::hide_about ()
2687 {
2688         if (about) {
2689                 about->get_window()->set_cursor ();
2690                 about->hide ();
2691         }
2692 }
2693
2694 void
2695 ARDOUR_UI::about_signal_response (int /*response*/)
2696 {
2697         hide_about();
2698 }
2699
2700 void
2701 ARDOUR_UI::show_splash ()
2702 {
2703         if (splash == 0) {
2704                 try {
2705                         splash = new Splash;
2706                 } catch (...) {
2707                         return;
2708                 }
2709         }
2710
2711         splash->show ();
2712         splash->present ();
2713         splash->queue_draw ();
2714         splash->get_window()->process_updates (true);
2715         flush_pending ();
2716 }
2717
2718 void
2719 ARDOUR_UI::hide_splash ()
2720 {
2721         if (splash) {
2722                 splash->hide();
2723         }
2724 }
2725
2726 void
2727 ARDOUR_UI::display_cleanup_results (ARDOUR::CleanupReport& rep, const gchar* list_title,
2728                                     const string& plural_msg, const string& singular_msg)
2729 {
2730         size_t removed;
2731
2732         removed = rep.paths.size();
2733
2734         if (removed == 0) {
2735                 MessageDialog msgd (*editor,
2736                                     _("No audio files were ready for cleanup"),
2737                                     true,
2738                                     Gtk::MESSAGE_INFO,
2739                                     (Gtk::ButtonsType)(Gtk::BUTTONS_OK)  );
2740                 msgd.set_secondary_text (_("If this seems suprising, \n\
2741 check for any existing snapshots.\n\
2742 These may still include regions that\n\
2743 require some unused files to continue to exist."));
2744
2745                 msgd.run ();
2746                 return;
2747         }
2748
2749         ArdourDialog results (_("ardour: cleanup"), true, false);
2750
2751         struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2752             CleanupResultsModelColumns() {
2753                     add (visible_name);
2754                     add (fullpath);
2755             }
2756             Gtk::TreeModelColumn<Glib::ustring> visible_name;
2757             Gtk::TreeModelColumn<Glib::ustring> fullpath;
2758         };
2759
2760
2761         CleanupResultsModelColumns results_columns;
2762         Glib::RefPtr<Gtk::ListStore> results_model;
2763         Gtk::TreeView results_display;
2764
2765         results_model = ListStore::create (results_columns);
2766         results_display.set_model (results_model);
2767         results_display.append_column (list_title, results_columns.visible_name);
2768
2769         results_display.set_name ("CleanupResultsList");
2770         results_display.set_headers_visible (true);
2771         results_display.set_headers_clickable (false);
2772         results_display.set_reorderable (false);
2773
2774         Gtk::ScrolledWindow list_scroller;
2775         Gtk::Label txt;
2776         Gtk::VBox dvbox;
2777         Gtk::HBox dhbox;  // the hbox for the image and text
2778         Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2779         Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO,  Gtk::ICON_SIZE_DIALOG));
2780
2781         dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2782
2783         const string dead_sound_directory = session->session_directory().dead_sound_path().to_string();
2784
2785
2786
2787
2788         /* subst:
2789            %1 - number of files removed
2790            %2 - location of "dead_sounds"
2791            %3 - size of files affected
2792            %4 - prefix for "bytes" to produce sensible results (e.g. mega, kilo, giga)
2793         */
2794
2795         const char* bprefix;
2796
2797         if (rep.space < 1048576.0f) {
2798                 bprefix = X_("kilo");
2799         } else if (rep.space < 1048576.0f * 1000) {
2800                 bprefix = X_("mega");
2801         } else {
2802                 bprefix = X_("giga");
2803         }
2804
2805         if (removed > 1) {
2806                 txt.set_text (string_compose (plural_msg, removed, dead_sound_directory, (float) rep.space / 1024.0f, bprefix));
2807         } else {
2808                 txt.set_text (string_compose (singular_msg, removed, dead_sound_directory, (float) rep.space / 1024.0f, bprefix));
2809         }
2810
2811         dhbox.pack_start (*dimage, true, false, 5);
2812         dhbox.pack_start (txt, true, false, 5);
2813
2814         for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2815                 TreeModel::Row row = *(results_model->append());
2816                 row[results_columns.visible_name] = *i;
2817                 row[results_columns.fullpath] = *i;
2818         }
2819
2820         list_scroller.add (results_display);
2821         list_scroller.set_size_request (-1, 150);
2822         list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2823
2824         dvbox.pack_start (dhbox, true, false, 5);
2825         dvbox.pack_start (list_scroller, true, false, 5);
2826         ddhbox.pack_start (dvbox, true, false, 5);
2827
2828         results.get_vbox()->pack_start (ddhbox, true, false, 5);
2829         results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2830         results.set_default_response (RESPONSE_CLOSE);
2831         results.set_position (Gtk::WIN_POS_MOUSE);
2832
2833         results_display.show();
2834         list_scroller.show();
2835         txt.show();
2836         dvbox.show();
2837         dhbox.show();
2838         ddhbox.show();
2839         dimage->show();
2840
2841         //results.get_vbox()->show();
2842         results.set_resizable (false);
2843
2844         results.run ();
2845
2846 }
2847
2848 void
2849 ARDOUR_UI::cleanup ()
2850 {
2851         if (session == 0) {
2852                 /* shouldn't happen: menu item is insensitive */
2853                 return;
2854         }
2855
2856
2857         MessageDialog  checker (_("Are you sure you want to cleanup?"),
2858                                 true,
2859                                 Gtk::MESSAGE_QUESTION,
2860                                 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2861
2862         checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2863 ALL undo/redo information will be lost if you cleanup.\n\
2864 After cleanup, unused audio files will be moved to a \
2865 \"dead sounds\" location."));
2866
2867         checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2868         checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2869         checker.set_default_response (RESPONSE_CANCEL);
2870
2871         checker.set_name (_("CleanupDialog"));
2872         checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2873         checker.set_position (Gtk::WIN_POS_MOUSE);
2874
2875         switch (checker.run()) {
2876         case RESPONSE_ACCEPT:
2877                 break;
2878         default:
2879                 return;
2880         }
2881
2882         ARDOUR::CleanupReport rep;
2883
2884         editor->prepare_for_cleanup ();
2885
2886         /* do not allow flush until a session is reloaded */
2887
2888         Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2889         if (act) {
2890                 act->set_sensitive (false);
2891         }
2892
2893         if (session->cleanup_sources (rep)) {
2894                 editor->finish_cleanup ();
2895                 return;
2896         }
2897
2898         editor->finish_cleanup ();
2899
2900         checker.hide();
2901         display_cleanup_results (rep,
2902                                  _("cleaned files"),
2903                                  _("\
2904 The following %1 files were not in use and \n\
2905 have been moved to:\n\
2906 %2. \n\n\
2907 Flushing the wastebasket will \n\
2908 release an additional\n\
2909 %3 %4bytes of disk space.\n"),
2910                                  _("\
2911 The following file was not in use and \n        \
2912 has been moved to:\n                            \
2913 %2. \n\n\
2914 Flushing the wastebasket will \n\
2915 release an additional\n\
2916 %3 %4bytes of disk space.\n"
2917                                          ));
2918
2919 }
2920
2921 void
2922 ARDOUR_UI::flush_trash ()
2923 {
2924         if (session == 0) {
2925                 /* shouldn't happen: menu item is insensitive */
2926                 return;
2927         }
2928
2929         ARDOUR::CleanupReport rep;
2930
2931         if (session->cleanup_trash_sources (rep)) {
2932                 return;
2933         }
2934
2935         display_cleanup_results (rep,
2936                                  _("deleted file"),
2937                                  _("The following %1 files were deleted from\n\
2938 %2,\n\
2939 releasing %3 %4bytes of disk space"),
2940                                  _("The following file was deleted from\n\
2941 %2,\n\
2942 releasing %3 %4bytes of disk space"));
2943 }
2944
2945 void
2946 ARDOUR_UI::add_route (Gtk::Window* float_window)
2947 {
2948         int count;
2949
2950         if (!session) {
2951                 return;
2952         }
2953
2954         if (add_route_dialog == 0) {
2955                 add_route_dialog = new AddRouteDialog (*session);
2956                 if (float_window) {
2957                         add_route_dialog->set_transient_for (*float_window);
2958                 }
2959         }
2960
2961         if (add_route_dialog->is_visible()) {
2962                 /* we're already doing this */
2963                 return;
2964         }
2965
2966         ResponseType r = (ResponseType) add_route_dialog->run ();
2967
2968         add_route_dialog->hide();
2969
2970         switch (r) {
2971                 case RESPONSE_ACCEPT:
2972                         break;
2973                 default:
2974                         return;
2975                         break;
2976         }
2977
2978         if ((count = add_route_dialog->count()) <= 0) {
2979                 return;
2980         }
2981
2982         string template_path = add_route_dialog->track_template();
2983
2984         if (!template_path.empty()) {
2985                 session->new_route_from_template (count, template_path);
2986                 return;
2987         }
2988
2989         uint32_t input_chan = add_route_dialog->channels ();
2990         uint32_t output_chan;
2991         string name_template = add_route_dialog->name_template ();
2992         bool track = add_route_dialog->track ();
2993         bool aux = !track && add_route_dialog->aux();
2994         RouteGroup* route_group = add_route_dialog->route_group ();
2995
2996         AutoConnectOption oac = Config->get_output_auto_connect();
2997
2998         if (oac & AutoConnectMaster) {
2999                 output_chan = (session->master_out() ? session->master_out()->n_inputs().n_audio() : input_chan);
3000         } else {
3001                 output_chan = input_chan;
3002         }
3003
3004         /* XXX do something with name template */
3005
3006         if (add_route_dialog->type() == ARDOUR::DataType::MIDI) {
3007                 if (track) {
3008                         session_add_midi_track (route_group, count);
3009                 } else  {
3010                         MessageDialog msg (*editor,
3011                                         _("Sorry, MIDI Busses are not supported at this time."));
3012                         msg.run ();
3013                         //session_add_midi_bus();
3014                 }
3015         } else {
3016                 if (track) {
3017                         session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), route_group, count);
3018                 } else {
3019                         session_add_audio_bus (aux, input_chan, output_chan, route_group, count);
3020                 }
3021         }
3022 }
3023
3024 XMLNode*
3025 ARDOUR_UI::mixer_settings () const
3026 {
3027         XMLNode* node = 0;
3028
3029         if (session) {
3030                 node = session->instant_xml(X_("Mixer"));
3031         } else {
3032                 node = Config->instant_xml(X_("Mixer"));
3033         }
3034
3035         if (!node) {
3036                 node = new XMLNode (X_("Mixer"));
3037         }
3038
3039         return node;
3040 }
3041
3042 XMLNode*
3043 ARDOUR_UI::editor_settings () const
3044 {
3045         XMLNode* node = 0;
3046
3047         if (session) {
3048                 node = session->instant_xml(X_("Editor"));
3049         } else {
3050                 node = Config->instant_xml(X_("Editor"));
3051         }
3052
3053         if (!node) {
3054                 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
3055                         node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
3056                 }
3057         }
3058
3059         if (!node) {
3060                 node = new XMLNode (X_("Editor"));
3061         }
3062
3063         return node;
3064 }
3065
3066 XMLNode*
3067 ARDOUR_UI::keyboard_settings () const
3068 {
3069         XMLNode* node = 0;
3070
3071         node = Config->extra_xml(X_("Keyboard"));
3072
3073         if (!node) {
3074                 node = new XMLNode (X_("Keyboard"));
3075         }
3076         return node;
3077 }
3078
3079 void
3080 ARDOUR_UI::create_xrun_marker(nframes_t where)
3081 {
3082         editor->mouse_add_new_marker (where, false, true);
3083 }
3084
3085 void
3086 ARDOUR_UI::halt_on_xrun_message ()
3087 {
3088         MessageDialog msg (*editor,
3089                            _("Recording was stopped because your system could not keep up."));
3090         msg.run ();
3091 }
3092
3093 void
3094 ARDOUR_UI::xrun_handler(nframes_t where)
3095 {
3096         if (!session) {
3097                 return;
3098         }
3099
3100         ENSURE_GUI_THREAD (bind(mem_fun(*this, &ARDOUR_UI::xrun_handler), where));
3101
3102         if (session && Config->get_create_xrun_marker() && session->actively_recording()) {
3103                 create_xrun_marker(where);
3104         }
3105
3106         if (session && Config->get_stop_recording_on_xrun() && session->actively_recording()) {
3107                 halt_on_xrun_message ();
3108         }
3109 }
3110
3111 void
3112 ARDOUR_UI::push_buffer_stats (uint32_t capture, uint32_t playback)
3113 {
3114         time_t now;
3115         time (&now);
3116
3117         while (disk_buffer_stats.size() > 60) {
3118                 disk_buffer_stats.pop_front ();
3119         }
3120
3121         disk_buffer_stats.push_back (DiskBufferStat (now, capture, playback));
3122 }
3123
3124 void
3125 ARDOUR_UI::write_buffer_stats ()
3126 {
3127
3128         std::ofstream fout;
3129         struct tm tm;
3130         char buf[64];
3131         char path[PATH_MAX+1];  int fd;
3132
3133         strcpy (path, "ardourBufferingXXXXXX");
3134
3135         if ((fd = mkstemp (path )) < 0) {
3136                 cerr << X_("cannot find temporary name for ardour buffer stats") << endl;
3137                 return;
3138         }
3139         
3140         fout.open (path);
3141         close (fd);
3142
3143         if (!fout) {
3144                 cerr << string_compose (X_("cannot open file %1 for ardour buffer stats"), path) << endl;
3145                 return;
3146         }
3147
3148         for (list<DiskBufferStat>::iterator i = disk_buffer_stats.begin(); i != disk_buffer_stats.end(); ++i) {
3149                 localtime_r (&(*i).when, &tm);
3150                 strftime (buf, sizeof (buf), "%T", &tm);
3151                 fout << buf << ' ' << (*i).capture << ' ' << (*i).playback << endl;
3152         }
3153         
3154         disk_buffer_stats.clear ();
3155
3156         fout.close ();
3157
3158         cerr << "Ardour buffering statistics can be found in: " << path << endl;
3159 }
3160
3161 void
3162 ARDOUR_UI::disk_overrun_handler ()
3163 {
3164         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
3165
3166         write_buffer_stats ();
3167
3168         if (!have_disk_speed_dialog_displayed) {
3169                 have_disk_speed_dialog_displayed = true;
3170                 MessageDialog* msg = new MessageDialog (*editor, _("\
3171 The disk system on your computer\n\
3172 was not able to keep up with Ardour.\n\
3173 \n\
3174 Specifically, it failed to write data to disk\n\
3175 quickly enough to keep up with recording.\n"));
3176                 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3177                 msg->show ();
3178         }
3179 }
3180
3181 void
3182 ARDOUR_UI::disk_underrun_handler ()
3183 {
3184         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3185
3186         write_buffer_stats ();
3187
3188         if (!have_disk_speed_dialog_displayed) {
3189                 have_disk_speed_dialog_displayed = true;
3190                 MessageDialog* msg = new MessageDialog (*editor,
3191                                    _("The disk system on your computer\n\
3192 was not able to keep up with Ardour.\n\
3193 \n\
3194 Specifically, it failed to read data from disk\n\
3195 quickly enough to keep up with playback.\n"));
3196                 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3197                 msg->show ();
3198         }
3199 }
3200
3201 void
3202 ARDOUR_UI::disk_speed_dialog_gone (int /*ignored_response*/, MessageDialog* msg)
3203 {
3204         have_disk_speed_dialog_displayed = false;
3205         delete msg;
3206 }
3207
3208 void
3209 ARDOUR_UI::session_dialog (std::string msg)
3210 {
3211         ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::session_dialog), msg));
3212
3213         MessageDialog* d;
3214
3215         if (editor) {
3216                 d = new MessageDialog (*editor, msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3217         } else {
3218                 d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3219         }
3220
3221         d->show_all ();
3222         d->run ();
3223         delete d;
3224 }
3225
3226 int
3227 ARDOUR_UI::pending_state_dialog ()
3228 {
3229         HBox* hbox = new HBox();
3230         Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3231         ArdourDialog dialog (_("Crash Recovery"), true);
3232         Label  message (_("\
3233 This session appears to have been in\n\
3234 middle of recording when ardour or\n\
3235 the computer was shutdown.\n\
3236 \n\
3237 Ardour can recover any captured audio for\n\
3238 you, or it can ignore it. Please decide\n\
3239 what you would like to do.\n"));
3240         image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3241         hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3242         hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3243         dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3244         dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3245         dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3246         dialog.set_default_response (RESPONSE_ACCEPT);
3247         dialog.set_position (WIN_POS_CENTER);
3248         message.show();
3249         image->show();
3250         hbox->show();
3251
3252         switch (dialog.run ()) {
3253         case RESPONSE_ACCEPT:
3254                 return 1;
3255         default:
3256                 return 0;
3257         }
3258 }
3259
3260 int
3261 ARDOUR_UI::sr_mismatch_dialog (nframes_t desired, nframes_t actual)
3262 {
3263         HBox* hbox = new HBox();
3264         Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3265         ArdourDialog dialog (_("Sample Rate Mismatch"), true);
3266         Label  message (string_compose (_("\
3267 This session was created with a sample rate of %1 Hz\n\
3268 \n\
3269 The audioengine is currently running at %2 Hz\n"), desired, actual));
3270
3271         image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3272         hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3273         hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3274         dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3275         dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
3276         dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
3277         dialog.set_default_response (RESPONSE_ACCEPT);
3278         dialog.set_position (WIN_POS_CENTER);
3279         message.show();
3280         image->show();
3281         hbox->show();
3282
3283         switch (dialog.run ()) {
3284         case RESPONSE_ACCEPT:
3285                 return 0;
3286         default:
3287                 return 1;
3288         }
3289 }
3290
3291
3292 void
3293 ARDOUR_UI::disconnect_from_jack ()
3294 {
3295         if (engine) {
3296                 if( engine->disconnect_from_jack ()) {
3297                         MessageDialog msg (*editor, _("Could not disconnect from JACK"));
3298                         msg.run ();
3299                 }
3300
3301                 update_sample_rate (0);
3302         }
3303 }
3304
3305 void
3306 ARDOUR_UI::reconnect_to_jack ()
3307 {
3308         if (engine) {
3309                 if (engine->reconnect_to_jack ()) {
3310                         MessageDialog msg (*editor,  _("Could not reconnect to JACK"));
3311                         msg.run ();
3312                 }
3313
3314                 update_sample_rate (0);
3315         }
3316 }
3317
3318 void
3319 ARDOUR_UI::use_config ()
3320 {
3321
3322         XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3323         if (node) {
3324                 set_transport_controllable_state (*node);
3325         }
3326 }
3327
3328 void
3329 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3330 {
3331         if (Config->get_primary_clock_delta_edit_cursor()) {
3332                 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
3333         } else {
3334                 primary_clock.set (pos, 0, true);
3335         }
3336
3337         if (Config->get_secondary_clock_delta_edit_cursor()) {
3338                 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
3339         } else {
3340                 secondary_clock.set (pos);
3341         }
3342
3343         if (big_clock_window) {
3344                 big_clock.set (pos);
3345         }
3346 }
3347
3348 void
3349 ARDOUR_UI::record_state_changed ()
3350 {
3351         ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
3352
3353         if (!session || !big_clock_window) {
3354                 /* why bother - the clock isn't visible */
3355                 return;
3356         }
3357
3358         Session::RecordState const r = session->record_status ();
3359         bool const h = session->have_rec_enabled_diskstream ();
3360
3361         if (r == Session::Recording && h)  {
3362                 big_clock.set_widget_name ("BigClockRecording");
3363         } else {
3364                 big_clock.set_widget_name ("BigClockNonRecording");
3365         }
3366 }
3367
3368 bool
3369 ARDOUR_UI::first_idle ()
3370 {
3371         if (session) {
3372                 session->allow_auto_play (true);
3373         }
3374
3375         if (editor) {
3376                 editor->first_idle();
3377         }
3378
3379         Keyboard::set_can_save_keybindings (true);
3380         return false;
3381 }
3382
3383 void
3384 ARDOUR_UI::store_clock_modes ()
3385 {
3386         XMLNode* node = new XMLNode(X_("ClockModes"));
3387
3388         for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3389                 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3390         }
3391
3392         session->add_extra_xml (*node);
3393         session->set_dirty ();
3394 }
3395
3396
3397
3398 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3399         : Controllable (name), ui (u), type(tp)
3400 {
3401
3402 }
3403
3404 void
3405 ARDOUR_UI::TransportControllable::set_value (float val)
3406 {
3407         if (type == ShuttleControl) {
3408                 double fract;
3409
3410                 if (val == 0.5f) {
3411                         fract = 0.0;
3412                 } else {
3413                         if (val < 0.5f) {
3414                                 fract = -((0.5f - val)/0.5f);
3415                         } else {
3416                                 fract = ((val - 0.5f)/0.5f);
3417                         }
3418                 }
3419
3420                 ui.set_shuttle_fract (fract);
3421                 return;
3422         }
3423
3424         if (val < 0.5f) {
3425                 /* do nothing: these are radio-style actions */
3426                 return;
3427         }
3428
3429         const char *action = 0;
3430
3431         switch (type) {
3432         case Roll:
3433                 action = X_("Roll");
3434                 break;
3435         case Stop:
3436                 action = X_("Stop");
3437                 break;
3438         case GotoStart:
3439                 action = X_("Goto Start");
3440                 break;
3441         case GotoEnd:
3442                 action = X_("Goto End");
3443                 break;
3444         case AutoLoop:
3445                 action = X_("Loop");
3446                 break;
3447         case PlaySelection:
3448                 action = X_("Play Selection");
3449                 break;
3450         case RecordEnable:
3451                 action = X_("Record");
3452                 break;
3453         default:
3454                 break;
3455         }
3456
3457         if (action == 0) {
3458                 return;
3459         }
3460
3461         Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3462
3463         if (act) {
3464                 act->activate ();
3465         }
3466 }
3467
3468 float
3469 ARDOUR_UI::TransportControllable::get_value (void) const
3470 {
3471         float val = 0.0f;
3472
3473         switch (type) {
3474         case Roll:
3475                 break;
3476         case Stop:
3477                 break;
3478         case GotoStart:
3479                 break;
3480         case GotoEnd:
3481                 break;
3482         case AutoLoop:
3483                 break;
3484         case PlaySelection:
3485                 break;
3486         case RecordEnable:
3487                 break;
3488         case ShuttleControl:
3489                 break;
3490         default:
3491                 break;
3492         }
3493
3494         return val;
3495 }
3496
3497 void
3498 ARDOUR_UI::TransportControllable::set_id (const string& str)
3499 {
3500         _id = str;
3501 }
3502
3503 void
3504 ARDOUR_UI::setup_profile ()
3505 {
3506         if (gdk_screen_width() < 1200) {
3507                 Profile->set_small_screen ();
3508         }
3509
3510
3511         if (getenv ("ARDOUR_SAE")) {
3512                 Profile->set_sae ();
3513                 Profile->set_single_package ();
3514         }
3515 }
3516