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