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