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