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