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