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