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