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