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