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