Revert internals of the last layering-related commit, and go back a slightly-cleaned...
[ardour.git] / gtk2_ardour / ardour_ui.cc
1 /*
2     Copyright (C) 1999-2007 Paul Davis
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #ifdef WAF_BUILD
21 #include "gtk2ardour-config.h"
22 #endif
23
24 #include <stdint.h>
25
26 #include <algorithm>
27 #include <cmath>
28 #include <fcntl.h>
29 #include <signal.h>
30 #include <unistd.h>
31 #include <time.h>
32 #include <cerrno>
33 #include <fstream>
34
35 #include <iostream>
36
37 #include <sys/resource.h>
38
39 #include <gtkmm/messagedialog.h>
40 #include <gtkmm/accelmap.h>
41
42 #include "pbd/error.h"
43 #include "pbd/basename.h"
44 #include "pbd/compose.h"
45 #include "pbd/failed_constructor.h"
46 #include "pbd/enumwriter.h"
47 #include "pbd/memento_command.h"
48 #include "pbd/openuri.h"
49 #include "pbd/file_utils.h"
50
51 #include "gtkmm2ext/application.h"
52 #include "gtkmm2ext/bindings.h"
53 #include "gtkmm2ext/gtk_ui.h"
54 #include "gtkmm2ext/utils.h"
55 #include "gtkmm2ext/click_box.h"
56 #include "gtkmm2ext/fastmeter.h"
57 #include "gtkmm2ext/popup.h"
58 #include "gtkmm2ext/window_title.h"
59
60 #include "midi++/manager.h"
61
62 #include "ardour/ardour.h"
63 #include "ardour/callback.h"
64 #include "ardour/profile.h"
65 #include "ardour/plugin_manager.h"
66 #include "ardour/session_directory.h"
67 #include "ardour/session_route.h"
68 #include "ardour/session_state_utils.h"
69 #include "ardour/session_utils.h"
70 #include "ardour/port.h"
71 #include "ardour/audioengine.h"
72 #include "ardour/playlist.h"
73 #include "ardour/utils.h"
74 #include "ardour/audio_diskstream.h"
75 #include "ardour/audiofilesource.h"
76 #include "ardour/recent_sessions.h"
77 #include "ardour/port.h"
78 #include "ardour/audio_track.h"
79 #include "ardour/midi_track.h"
80 #include "ardour/filesystem_paths.h"
81 #include "ardour/filename_extensions.h"
82 #include "ardour/process_thread.h"
83
84 typedef uint64_t microseconds_t;
85
86 #include "about.h"
87 #include "actions.h"
88 #include "add_route_dialog.h"
89 #include "ambiguous_file_dialog.h"
90 #include "ardour_ui.h"
91 #include "audio_clock.h"
92 #include "bundle_manager.h"
93 #include "engine_dialog.h"
94 #include "gain_meter.h"
95 #include "global_port_matrix.h"
96 #include "gui_object.h"
97 #include "gui_thread.h"
98 #include "keyboard.h"
99 #include "location_ui.h"
100 #include "missing_file_dialog.h"
101 #include "missing_plugin_dialog.h"
102 #include "mixer_ui.h"
103 #include "opts.h"
104 #include "processor_box.h"
105 #include "prompter.h"
106 #include "public_editor.h"
107 #include "route_time_axis.h"
108 #include "session_metadata_dialog.h"
109 #include "shuttle_control.h"
110 #include "speaker_dialog.h"
111 #include "splash.h"
112 #include "startup.h"
113 #include "theme_manager.h"
114 #include "time_axis_view_item.h"
115 #include "utils.h"
116 #include "window_proxy.h"
117
118 #include "i18n.h"
119
120 using namespace ARDOUR;
121 using namespace PBD;
122 using namespace Gtkmm2ext;
123 using namespace Gtk;
124
125 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
126 UIConfiguration *ARDOUR_UI::ui_config = 0;
127
128 sigc::signal<void,bool> ARDOUR_UI::Blink;
129 sigc::signal<void>      ARDOUR_UI::RapidScreenUpdate;
130 sigc::signal<void>      ARDOUR_UI::SuperRapidScreenUpdate;
131 sigc::signal<void, framepos_t, bool, framepos_t> ARDOUR_UI::Clock;
132
133 bool could_be_a_valid_path (const string& path);
134
135 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
136
137         : Gtkmm2ext::UI (PROGRAM_NAME, argcp, argvp)
138
139         , gui_object_state (new GUIObjectState)
140         , primary_clock (new AudioClock (X_("primary"), false, X_("transport"), true, true, false, true))
141         , secondary_clock (new AudioClock (X_("secondary"), false, X_("secondary"), true, true, false, true))
142
143           /* big clock */
144
145         , big_clock (new AudioClock (X_("bigclock"), false, "big", true, true, false, false))
146
147           /* transport */
148
149         , roll_controllable (new TransportControllable ("transport roll", *this, TransportControllable::Roll))
150         , stop_controllable (new TransportControllable ("transport stop", *this, TransportControllable::Stop))
151         , goto_start_controllable (new TransportControllable ("transport goto start", *this, TransportControllable::GotoStart))
152         , goto_end_controllable (new TransportControllable ("transport goto end", *this, TransportControllable::GotoEnd))
153         , auto_loop_controllable (new TransportControllable ("transport auto loop", *this, TransportControllable::AutoLoop))
154         , play_selection_controllable (new TransportControllable ("transport play selection", *this, TransportControllable::PlaySelection))
155         , rec_controllable (new TransportControllable ("transport rec-enable", *this, TransportControllable::RecordEnable))
156
157         , auto_return_button (ArdourButton::led_default_elements)
158         , auto_play_button (ArdourButton::led_default_elements)
159         , auto_input_button (ArdourButton::led_default_elements)
160
161         , auditioning_alert_button (_("audition"))
162         , solo_alert_button (_("solo"))
163         , feedback_alert_button (_("feedback"))
164
165         , error_log_button (_("Errors"))
166
167         , _status_bar_visibility (X_("status-bar"))
168         , _feedback_exists (false)
169
170 {
171         using namespace Gtk::Menu_Helpers;
172
173         Gtkmm2ext::init();
174
175
176 #ifdef TOP_MENUBAR
177         // _auto_display_errors = false;
178         /*
179          * This was commented out as it wasn't defined
180          * in A3 IIRC.  If this is not needed it should
181          * be completely removed.
182          */
183 #endif
184
185         about = 0;
186         splash = 0;
187         _startup = 0;
188
189         if (theArdourUI == 0) {
190                 theArdourUI = this;
191         }
192
193         ui_config = new UIConfiguration();
194         theme_manager = new ThemeManager();
195
196         key_editor = 0;
197
198         editor = 0;
199         mixer = 0;
200         editor = 0;
201         engine = 0;
202         _session_is_new = false;
203         big_clock_window = 0;
204         big_clock_height = 0;
205         big_clock_resize_in_progress = false;
206         session_selector_window = 0;
207         last_key_press_time = 0;
208         _will_create_new_session_automatically = false;
209         add_route_dialog = 0;
210         route_params = 0;
211         bundle_manager = 0;
212         rc_option_editor = 0;
213         session_option_editor = 0;
214         location_ui = 0;
215         open_session_selector = 0;
216         have_configure_timeout = false;
217         have_disk_speed_dialog_displayed = false;
218         session_loaded = false;
219         ignore_dual_punch = false;
220         original_big_clock_width = -1;
221         original_big_clock_height = -1;
222         original_big_clock_font_size = 0;
223
224         roll_button.set_controllable (roll_controllable);
225         stop_button.set_controllable (stop_controllable);
226         goto_start_button.set_controllable (goto_start_controllable);
227         goto_end_button.set_controllable (goto_end_controllable);
228         auto_loop_button.set_controllable (auto_loop_controllable);
229         play_selection_button.set_controllable (play_selection_controllable);
230         rec_button.set_controllable (rec_controllable);
231
232         roll_button.set_name ("transport button");
233         stop_button.set_name ("transport button");
234         goto_start_button.set_name ("transport button");
235         goto_end_button.set_name ("transport button");
236         auto_loop_button.set_name ("transport button");
237         play_selection_button.set_name ("transport button");
238         rec_button.set_name ("transport recenable button");
239         join_play_range_button.set_name ("transport button");
240         midi_panic_button.set_name ("transport button");
241
242         goto_start_button.set_tweaks (ArdourButton::ShowClick);
243         goto_end_button.set_tweaks (ArdourButton::ShowClick);
244         midi_panic_button.set_tweaks (ArdourButton::ShowClick);
245         
246         last_configure_time= 0;
247         last_peak_grab = 0;
248
249         ARDOUR::Diskstream::DiskOverrun.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::disk_overrun_handler, this), gui_context());
250         ARDOUR::Diskstream::DiskUnderrun.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::disk_underrun_handler, this), gui_context());
251
252         /* handle dialog requests */
253
254         ARDOUR::Session::Dialog.connect (forever_connections, MISSING_INVALIDATOR, ui_bind (&ARDOUR_UI::session_dialog, this, _1), gui_context());
255
256         /* handle pending state with a dialog (PROBLEM: needs to return a value and thus cannot be x-thread) */
257
258         ARDOUR::Session::AskAboutPendingState.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::pending_state_dialog, this));
259
260         /* handle sr mismatch with a dialog (PROBLEM: needs to return a value and thus cannot be x-thread) */
261
262         ARDOUR::Session::AskAboutSampleRateMismatch.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::sr_mismatch_dialog, this, _1, _2));
263
264         /* handle requests to quit (coming from JACK session) */
265
266         ARDOUR::Session::Quit.connect (forever_connections, MISSING_INVALIDATOR, ui_bind (&ARDOUR_UI::finish, this), gui_context ());
267
268         /* tell the user about feedback */
269
270         ARDOUR::Session::FeedbackDetected.connect (forever_connections, MISSING_INVALIDATOR, ui_bind (&ARDOUR_UI::feedback_detected, this), gui_context ());
271         ARDOUR::Session::SuccessfulGraphSort.connect (forever_connections, MISSING_INVALIDATOR, ui_bind (&ARDOUR_UI::successful_graph_sort, this), gui_context ());
272
273         /* handle requests to deal with missing files */
274
275         ARDOUR::Session::MissingFile.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::missing_file, this, _1, _2, _3));
276
277         /* and ambiguous files */
278
279         ARDOUR::FileSource::AmbiguousFileName.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::ambiguous_file, this, _1, _2, _3));
280
281         /* lets get this party started */
282
283         try {
284                 if (ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst, ARDOUR_COMMAND_LINE::try_hw_optimization)) {
285                         throw failed_constructor ();
286                 }
287
288                 setup_gtk_ardour_enums ();
289                 setup_profile ();
290
291                 GainMeter::setup_slider_pix ();
292                 RouteTimeAxisView::setup_slider_pix ();
293                 SendProcessorEntry::setup_slider_pix ();
294                 SessionEvent::create_per_thread_pool ("GUI", 512);
295
296         } catch (failed_constructor& err) {
297                 error << string_compose (_("could not initialize %1."), PROGRAM_NAME) << endmsg;
298                 // pass it on up
299                 throw;
300         }
301
302         /* we like keyboards */
303
304         keyboard = new ArdourKeyboard(*this);
305
306         XMLNode* node = ARDOUR_UI::instance()->keyboard_settings();
307         if (node) {
308                 keyboard->set_state (*node, Stateful::loading_state_version);
309         }
310
311         /* we don't like certain modifiers */
312         Bindings::set_ignored_state (GDK_LOCK_MASK|GDK_MOD2_MASK|GDK_MOD3_MASK);
313
314         reset_dpi();
315
316         TimeAxisViewItem::set_constant_heights ();
317
318         /* The following must happen after ARDOUR::init() so that Config is set up */
319
320         location_ui = new ActionWindowProxy<LocationUIWindow> (X_("locations"), Config->extra_xml (X_("UI")), X_("ToggleLocations"));
321         big_clock_window = new ActionWindowProxy<Gtk::Window> (X_("bigclock"), Config->extra_xml (X_("UI")), X_("ToggleBigClock"));
322         speaker_config_window = new ActionWindowProxy<SpeakerDialog> (X_("speakerconf"), Config->extra_xml (X_("UI")), X_("toggle-speaker-config"));
323
324         for (ARDOUR::DataType::iterator i = ARDOUR::DataType::begin(); i != ARDOUR::DataType::end(); ++i) {
325                 _global_port_matrix[*i] = new ActionWindowProxy<GlobalPortMatrixWindow> (
326                         string_compose ("GlobalPortMatrix-%1", (*i).to_string()),
327                         Config->extra_xml (X_("UI")),
328                         string_compose ("toggle-%1-connection-manager", (*i).to_string())
329                         );
330         }
331
332         setup_clock ();
333
334         SpeakerDialog* s = new SpeakerDialog ();
335         s->signal_unmap().connect (sigc::bind (sigc::ptr_fun (&ActionManager::uncheck_toggleaction), X_("<Actions>/Common/toggle-speaker-config")));
336         speaker_config_window->set (s);
337
338         starting.connect (sigc::mem_fun(*this, &ARDOUR_UI::startup));
339         stopping.connect (sigc::mem_fun(*this, &ARDOUR_UI::shutdown));
340
341         _process_thread = new ProcessThread ();
342         _process_thread->init ();
343
344         DPIReset.connect (sigc::mem_fun (*this, &ARDOUR_UI::resize_text_widgets));
345 }
346
347 /** @return true if a session was chosen and `apply' clicked, otherwise false if `cancel' was clicked */
348 bool
349 ARDOUR_UI::run_startup (bool should_be_new, string load_template)
350 {
351         delete _startup;
352         _startup = new ArdourStartup ();
353
354         XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
355
356         if (audio_setup && _startup->engine_control()) {
357                 _startup->engine_control()->set_state (*audio_setup);
358         }
359
360         _startup->set_new_only (should_be_new);
361         if (!load_template.empty()) {
362                 _startup->set_load_template( load_template );
363         }
364         _startup->present ();
365
366         main().run();
367
368         _startup->hide ();
369
370         switch (_startup->response()) {
371         case RESPONSE_OK:
372                 return true;
373         default:
374                 return false;
375         }
376 }
377
378 int
379 ARDOUR_UI::create_engine ()
380 {
381         // this gets called every time by new_session()
382
383         if (engine) {
384                 return 0;
385         }
386
387         loading_message (_("Starting audio engine"));
388
389         try {
390                 engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name, ARDOUR_COMMAND_LINE::jack_session_uuid);
391
392         } catch (...) {
393
394                 return -1;
395         }
396
397         engine->Stopped.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::engine_stopped, this), gui_context());
398         engine->Running.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::engine_running, this), gui_context());
399         engine->SampleRateChanged.connect (forever_connections, MISSING_INVALIDATOR, ui_bind (&ARDOUR_UI::update_sample_rate, this, _1), gui_context());
400
401         engine->Halted.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::engine_halted, this, _1, false));
402
403         ARDOUR::Port::set_connecting_blocked (ARDOUR_COMMAND_LINE::no_connect_ports);
404
405         post_engine ();
406
407         return 0;
408 }
409
410 void
411 ARDOUR_UI::post_engine ()
412 {
413         /* Things to be done once we create the AudioEngine
414          */
415
416         ARDOUR::init_post_engine ();
417
418         /* load up the UI manager */
419
420         ActionManager::init ();
421
422         _tooltips.enable();
423
424         if (setup_windows ()) {
425                 throw failed_constructor ();
426         }
427
428         /* Do this after setup_windows (), as that's when the _status_bar_visibility is created */
429         XMLNode* n = Config->extra_xml (X_("UI"));
430         if (n) {
431                 _status_bar_visibility.set_state (*n);
432         }
433         
434         check_memory_locking();
435
436         /* this is the first point at which all the keybindings are available */
437
438         if (ARDOUR_COMMAND_LINE::show_key_actions) {
439                 vector<string> names;
440                 vector<string> paths;
441                 vector<string> tooltips;
442                 vector<string> keys;
443                 vector<AccelKey> bindings;
444
445                 ActionManager::get_all_actions (names, paths, tooltips, keys, bindings);
446
447                 vector<string>::iterator n;
448                 vector<string>::iterator k;
449                 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
450                         cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
451                 }
452
453                 exit (0);
454         }
455
456         blink_timeout_tag = -1;
457
458         /* this being a GUI and all, we want peakfiles */
459
460         AudioFileSource::set_build_peakfiles (true);
461         AudioFileSource::set_build_missing_peakfiles (true);
462
463         /* set default clock modes */
464
465         if (Profile->get_sae()) {
466                 primary_clock->set_mode (AudioClock::BBT);
467                 secondary_clock->set_mode (AudioClock::MinSec);
468         }  else {
469                 primary_clock->set_mode (AudioClock::Timecode);
470                 secondary_clock->set_mode (AudioClock::BBT);
471         }
472
473         /* start the time-of-day-clock */
474
475 #ifndef GTKOSX
476         /* OS X provides a nearly-always visible wallclock, so don't be stupid */
477         update_wall_clock ();
478         Glib::signal_timeout().connect (sigc::mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
479 #endif
480
481         update_disk_space ();
482         update_cpu_load ();
483         update_sample_rate (engine->frame_rate());
484
485         Config->ParameterChanged.connect (forever_connections, MISSING_INVALIDATOR, ui_bind (&ARDOUR_UI::parameter_changed, this, _1), gui_context());
486         boost::function<void (string)> pc (boost::bind (&ARDOUR_UI::parameter_changed, this, _1));
487         Config->map_parameters (pc);
488
489         /* now start and maybe save state */
490
491         if (do_engine_start () == 0) {
492                 if (_session && _session_is_new) {
493                         /* we need to retain initial visual
494                            settings for a new session
495                         */
496                         _session->save_state ("");
497                 }
498         }
499 }
500
501 ARDOUR_UI::~ARDOUR_UI ()
502 {
503         delete keyboard;
504         delete editor;
505         delete mixer;
506         delete add_route_dialog;
507 }
508
509 void
510 ARDOUR_UI::pop_back_splash ()
511 {
512         if (Splash::instance()) {
513                 // Splash::instance()->pop_back();
514                 Splash::instance()->hide ();
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 ();
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 ();
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();
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 ();
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, string const & name_template)
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 (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                 } /*else {
1467                         if ((route = _session->new_midi_route ()) == 0) {
1468                                 error << _("could not create new midi bus") << endmsg;
1469                         }
1470                 }*/
1471         }
1472
1473         catch (...) {
1474                 MessageDialog msg (*editor,
1475                                    string_compose (_("There are insufficient JACK ports available\n\
1476 to create a new track or bus.\n\
1477 You should save %1, exit and\n\
1478 restart JACK with more ports."), PROGRAM_NAME));
1479                 msg.run ();
1480         }
1481 }
1482
1483
1484 void
1485 ARDOUR_UI::session_add_audio_route (
1486         bool track,
1487         int32_t input_channels,
1488         int32_t output_channels,
1489         ARDOUR::TrackMode mode,
1490         RouteGroup* route_group,
1491         uint32_t how_many,
1492         string const & name_template
1493         )
1494 {
1495         list<boost::shared_ptr<AudioTrack> > tracks;
1496         RouteList routes;
1497
1498         if (_session == 0) {
1499                 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1500                 return;
1501         }
1502
1503         try {
1504                 if (track) {
1505                         tracks = _session->new_audio_track (input_channels, output_channels, mode, route_group, how_many, name_template);
1506
1507                         if (tracks.size() != how_many) {
1508                                 if (how_many == 1) {
1509                                         error << _("could not create a new audio track") << endmsg;
1510                                 } else {
1511                                         error << string_compose (_("could only create %1 of %2 new audio %3"),
1512                                                                  tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1513                                 }
1514                         }
1515
1516                 } else {
1517
1518                         routes = _session->new_audio_route (input_channels, output_channels, route_group, how_many, name_template);
1519
1520                         if (routes.size() != how_many) {
1521                                 if (how_many == 1) {
1522                                         error << _("could not create a new audio bus") << endmsg;
1523                                 } else {
1524                                         error << string_compose (_("could not create %1 new audio busses"), how_many) << endmsg;
1525                                 }
1526                         }
1527                 }
1528         }
1529
1530         catch (...) {
1531                 MessageDialog msg (*editor,
1532                                    string_compose (_("There are insufficient JACK ports available\n\
1533 to create a new track or bus.\n\
1534 You should save %1, exit and\n\
1535 restart JACK with more ports."), PROGRAM_NAME));
1536                 pop_back_splash ();
1537                 msg.run ();
1538         }
1539 }
1540
1541 void
1542 ARDOUR_UI::do_transport_locate (framepos_t new_position, bool with_roll)
1543 {
1544         framecnt_t _preroll = 0;
1545
1546         if (_session) {
1547                 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1548                 // _preroll = _session->convert_to_frames_at (new_position, Config->get_preroll());
1549
1550                 if (new_position > _preroll) {
1551                         new_position -= _preroll;
1552                 } else {
1553                         new_position = 0;
1554                 }
1555
1556                 _session->request_locate (new_position, with_roll);
1557         }
1558 }
1559
1560 void
1561 ARDOUR_UI::transport_goto_start ()
1562 {
1563         if (_session) {
1564                 _session->goto_start();
1565
1566                 /* force displayed area in editor to start no matter
1567                    what "follow playhead" setting is.
1568                 */
1569
1570                 if (editor) {
1571                         editor->center_screen (_session->current_start_frame ());
1572                 }
1573         }
1574 }
1575
1576 void
1577 ARDOUR_UI::transport_goto_zero ()
1578 {
1579         if (_session) {
1580                 _session->request_locate (0);
1581
1582                 /* force displayed area in editor to start no matter
1583                    what "follow playhead" setting is.
1584                 */
1585
1586                 if (editor) {
1587                         editor->reset_x_origin (0);
1588                 }
1589         }
1590 }
1591
1592 void
1593 ARDOUR_UI::transport_goto_wallclock ()
1594 {
1595         if (_session && editor) {
1596
1597                 time_t now;
1598                 struct tm tmnow;
1599                 framepos_t frames;
1600
1601                 time (&now);
1602                 localtime_r (&now, &tmnow);
1603
1604                 frames = tmnow.tm_hour * (60 * 60 * _session->frame_rate());
1605                 frames += tmnow.tm_min * (60 * _session->frame_rate());
1606                 frames += tmnow.tm_sec * _session->frame_rate();
1607
1608                 _session->request_locate (frames, _session->transport_rolling ());
1609
1610                 /* force displayed area in editor to start no matter
1611                    what "follow playhead" setting is.
1612                 */
1613
1614                 if (editor) {
1615                         editor->center_screen (frames);
1616                 }
1617         }
1618 }
1619
1620 void
1621 ARDOUR_UI::transport_goto_end ()
1622 {
1623         if (_session) {
1624                 framepos_t const frame = _session->current_end_frame();
1625                 _session->request_locate (frame);
1626
1627                 /* force displayed area in editor to start no matter
1628                    what "follow playhead" setting is.
1629                 */
1630
1631                 if (editor) {
1632                         editor->center_screen (frame);
1633                 }
1634         }
1635 }
1636
1637 void
1638 ARDOUR_UI::transport_stop ()
1639 {
1640         if (!_session) {
1641                 return;
1642         }
1643
1644         if (_session->is_auditioning()) {
1645                 _session->cancel_audition ();
1646                 return;
1647         }
1648
1649         _session->request_stop (false, true);
1650 }
1651
1652 void
1653 ARDOUR_UI::transport_stop_and_forget_capture ()
1654 {
1655         if (_session) {
1656                 _session->request_stop (true, true);
1657         }
1658 }
1659
1660 void
1661 ARDOUR_UI::remove_last_capture()
1662 {
1663         if (editor) {
1664                 editor->remove_last_capture();
1665         }
1666 }
1667
1668 void
1669 ARDOUR_UI::transport_record (bool roll)
1670 {
1671
1672         if (_session) {
1673                 switch (_session->record_status()) {
1674                 case Session::Disabled:
1675                         if (_session->ntracks() == 0) {
1676                                 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."));
1677                                 msg.run ();
1678                                 return;
1679                         }
1680                         _session->maybe_enable_record ();
1681                         if (roll) {
1682                                 transport_roll ();
1683                         }
1684                         break;
1685                 case Session::Recording:
1686                         if (roll) {
1687                                 _session->request_stop();
1688                         } else {
1689                                 _session->disable_record (false, true);
1690                         }
1691                         break;
1692
1693                 case Session::Enabled:
1694                         _session->disable_record (false, true);
1695                 }
1696         }
1697         //cerr << "ARDOUR_UI::transport_record () called roll = " << roll << " _session->record_status() = " << _session->record_status() << endl;
1698 }
1699
1700 void
1701 ARDOUR_UI::transport_roll ()
1702 {
1703         if (!_session) {
1704                 return;
1705         }
1706
1707         if (_session->is_auditioning()) {
1708                 return;
1709         }
1710
1711 #if 0
1712         if (_session->config.get_external_sync()) {
1713                 switch (_session->config.get_sync_source()) {
1714                 case JACK:
1715                         break;
1716                 default:
1717                         /* transport controlled by the master */
1718                         return;
1719                 }
1720         }
1721 #endif
1722
1723         bool rolling = _session->transport_rolling();
1724
1725         if (_session->get_play_loop()) {
1726                 /* XXX it is not possible to just leave seamless loop and keep
1727                    playing at present (nov 4th 2009)
1728                 */
1729                 if (!Config->get_seamless_loop()) {
1730                         _session->request_play_loop (false, true);
1731                 }
1732         } else if (_session->get_play_range () && !join_play_range_button.active_state()) {
1733                 /* stop playing a range if we currently are */
1734                 _session->request_play_range (0, true);
1735         }
1736
1737         if (join_play_range_button.active_state()) {
1738                 _session->request_play_range (&editor->get_selection().time, true);
1739         }
1740
1741         if (!rolling) {
1742                 _session->request_transport_speed (1.0f);
1743         }
1744 }
1745
1746 void
1747 ARDOUR_UI::toggle_roll (bool with_abort, bool roll_out_of_bounded_mode)
1748 {
1749
1750         if (!_session) {
1751                 return;
1752         }
1753
1754         if (_session->is_auditioning()) {
1755                 _session->cancel_audition ();
1756                 return;
1757         }
1758
1759         if (_session->config.get_external_sync()) {
1760                 switch (_session->config.get_sync_source()) {
1761                 case JACK:
1762                         break;
1763                 default:
1764                         /* transport controlled by the master */
1765                         return;
1766                 }
1767         }
1768
1769         bool rolling = _session->transport_rolling();
1770         bool affect_transport = true;
1771
1772         if (rolling && roll_out_of_bounded_mode) {
1773                 /* drop out of loop/range playback but leave transport rolling */
1774                 if (_session->get_play_loop()) {
1775                         if (Config->get_seamless_loop()) {
1776                                 /* the disk buffers contain copies of the loop - we can't
1777                                    just keep playing, so stop the transport. the user
1778                                    can restart as they wish.
1779                                 */
1780                                 affect_transport = true;
1781                         } else {
1782                                 /* disk buffers are normal, so we can keep playing */
1783                                 affect_transport = false;
1784                         }
1785                         _session->request_play_loop (false, true);
1786                 } else if (_session->get_play_range ()) {
1787                         affect_transport = false;
1788                         _session->request_play_range (0, true);
1789                 }
1790         }
1791
1792         if (affect_transport) {
1793                 if (rolling) {
1794                         _session->request_stop (with_abort, true);
1795                 } else {
1796                         if (join_play_range_button.active_state()) {
1797                                 _session->request_play_range (&editor->get_selection().time, true);
1798                         }
1799
1800                         _session->request_transport_speed (1.0f);
1801                 }
1802         }
1803 }
1804
1805 void
1806 ARDOUR_UI::toggle_session_auto_loop ()
1807 {
1808         if (!_session) {
1809                 return;
1810         }
1811
1812         if (_session->get_play_loop()) {
1813
1814                 if (_session->transport_rolling()) {
1815
1816                         Location * looploc = _session->locations()->auto_loop_location();
1817
1818                         if (looploc) {
1819                                 _session->request_locate (looploc->start(), true);
1820                                 _session->request_play_loop (false);
1821                         }
1822
1823                 } else {
1824                         _session->request_play_loop (false);
1825                 }
1826         } else {
1827
1828           Location * looploc = _session->locations()->auto_loop_location();
1829
1830                 if (looploc) {
1831                         _session->request_play_loop (true);
1832                 }
1833         }
1834 }
1835
1836 void
1837 ARDOUR_UI::transport_play_selection ()
1838 {
1839         if (!_session) {
1840                 return;
1841         }
1842
1843         editor->play_selection ();
1844 }
1845
1846 void
1847 ARDOUR_UI::transport_rewind (int option)
1848 {
1849         float current_transport_speed;
1850
1851         if (_session) {
1852                 current_transport_speed = _session->transport_speed();
1853
1854                 if (current_transport_speed >= 0.0f) {
1855                         switch (option) {
1856                         case 0:
1857                                 _session->request_transport_speed (-1.0f);
1858                                 break;
1859                         case 1:
1860                                 _session->request_transport_speed (-4.0f);
1861                                 break;
1862                         case -1:
1863                                 _session->request_transport_speed (-0.5f);
1864                                 break;
1865                         }
1866                 } else {
1867                         /* speed up */
1868                         _session->request_transport_speed (current_transport_speed * 1.5f);
1869                 }
1870         }
1871 }
1872
1873 void
1874 ARDOUR_UI::transport_forward (int option)
1875 {
1876         float current_transport_speed;
1877
1878         if (_session) {
1879                 current_transport_speed = _session->transport_speed();
1880
1881                 if (current_transport_speed <= 0.0f) {
1882                         switch (option) {
1883                         case 0:
1884                                 _session->request_transport_speed (1.0f);
1885                                 break;
1886                         case 1:
1887                                 _session->request_transport_speed (4.0f);
1888                                 break;
1889                         case -1:
1890                                 _session->request_transport_speed (0.5f);
1891                                 break;
1892                         }
1893                 } else {
1894                         /* speed up */
1895                         _session->request_transport_speed (current_transport_speed * 1.5f);
1896                 }
1897
1898         }
1899 }
1900
1901 void
1902 ARDOUR_UI::toggle_record_enable (uint32_t rid)
1903 {
1904         if (_session == 0) {
1905                 return;
1906         }
1907
1908         boost::shared_ptr<Route> r;
1909
1910         if ((r = _session->route_by_remote_id (rid)) != 0) {
1911
1912                 Track* t;
1913
1914                 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1915                         t->set_record_enabled (!t->record_enabled(), this);
1916                 }
1917         }
1918         if (_session == 0) {
1919                 return;
1920         }
1921 }
1922
1923 void
1924 ARDOUR_UI::map_transport_state ()
1925 {
1926         if (!_session) {
1927                 auto_loop_button.unset_active_state ();
1928                 play_selection_button.unset_active_state ();
1929                 roll_button.unset_active_state ();
1930                 stop_button.set_active_state (Gtkmm2ext::Active);
1931                 return;
1932         }
1933
1934         shuttle_box->map_transport_state ();
1935
1936         float sp = _session->transport_speed();
1937
1938         if (sp != 0.0f) {
1939
1940                 /* we're rolling */
1941
1942                 if (_session->get_play_range()) {
1943
1944                         play_selection_button.set_active_state (Gtkmm2ext::Active);
1945                         roll_button.unset_active_state ();
1946                         auto_loop_button.unset_active_state ();
1947
1948                 } else if (_session->get_play_loop ()) {
1949
1950                         auto_loop_button.set_active_state (Gtkmm2ext::Active);
1951                         play_selection_button.unset_active_state ();
1952                         roll_button.unset_active_state ();
1953
1954                 } else {
1955
1956                         roll_button.set_active_state (Gtkmm2ext::Active);
1957                         play_selection_button.unset_active_state ();
1958                         auto_loop_button.unset_active_state ();
1959                 }
1960
1961                 if (join_play_range_button.active_state()) {
1962                         /* light up both roll and play-selection if they are joined */
1963                         roll_button.set_active_state (Gtkmm2ext::Active);
1964                         play_selection_button.set_active_state (Gtkmm2ext::Active);
1965                 }
1966
1967                 stop_button.unset_active_state ();
1968
1969         } else {
1970
1971                 stop_button.set_active_state (Gtkmm2ext::Active);
1972                 roll_button.unset_active_state ();
1973                 play_selection_button.unset_active_state ();
1974                 auto_loop_button.unset_active_state ();
1975                 update_disk_space ();
1976         }
1977 }
1978
1979 void
1980 ARDOUR_UI::engine_stopped ()
1981 {
1982         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::engine_stopped)
1983         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1984         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1985 }
1986
1987 void
1988 ARDOUR_UI::engine_running ()
1989 {
1990         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::engine_running)
1991         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1992         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1993
1994         Glib::RefPtr<Action> action;
1995         const char* action_name = 0;
1996
1997         switch (engine->frames_per_cycle()) {
1998         case 32:
1999                 action_name = X_("JACKLatency32");
2000                 break;
2001         case 64:
2002                 action_name = X_("JACKLatency64");
2003                 break;
2004         case 128:
2005                 action_name = X_("JACKLatency128");
2006                 break;
2007         case 512:
2008                 action_name = X_("JACKLatency512");
2009                 break;
2010         case 1024:
2011                 action_name = X_("JACKLatency1024");
2012                 break;
2013         case 2048:
2014                 action_name = X_("JACKLatency2048");
2015                 break;
2016         case 4096:
2017                 action_name = X_("JACKLatency4096");
2018                 break;
2019         case 8192:
2020                 action_name = X_("JACKLatency8192");
2021                 break;
2022         default:
2023                 /* XXX can we do anything useful ? */
2024                 break;
2025         }
2026
2027         if (action_name) {
2028
2029                 action = ActionManager::get_action (X_("JACK"), action_name);
2030
2031                 if (action) {
2032                         Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
2033                         ract->set_active ();
2034                 }
2035         }
2036 }
2037
2038 void
2039 ARDOUR_UI::engine_halted (const char* reason, bool free_reason)
2040 {
2041         if (!Gtkmm2ext::UI::instance()->caller_is_ui_thread()) {
2042                 /* we can't rely on the original string continuing to exist when we are called
2043                    again in the GUI thread, so make a copy and note that we need to
2044                    free it later.
2045                 */
2046                 char *copy = strdup (reason);
2047                 Gtkmm2ext::UI::instance()->call_slot (invalidator (*this), boost::bind (&ARDOUR_UI::engine_halted, this, copy, true));
2048                 return;
2049         }
2050
2051         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
2052         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
2053
2054         update_sample_rate (0);
2055
2056         string msgstr;
2057
2058         /* if the reason is a non-empty string, it means that the backend was shutdown
2059            rather than just Ardour.
2060         */
2061
2062         if (strlen (reason)) {
2063                 msgstr = string_compose (_("The audio backend (JACK) was shutdown because:\n\n%1"), reason);
2064         } else {
2065                 msgstr = string_compose (_("\
2066 JACK has either been shutdown or it\n\
2067 disconnected %1 because %1\n\
2068 was not fast enough. Try to restart\n\
2069 JACK, reconnect and save the session."), PROGRAM_NAME);
2070         }
2071
2072         MessageDialog msg (*editor, msgstr);
2073         pop_back_splash ();
2074         msg.run ();
2075
2076         if (free_reason) {
2077                 free ((char*) reason);
2078         }
2079 }
2080
2081 int32_t
2082 ARDOUR_UI::do_engine_start ()
2083 {
2084         try {
2085                 engine->start();
2086         }
2087
2088         catch (...) {
2089                 engine->stop ();
2090                 error << _("Unable to start the session running")
2091                       << endmsg;
2092                 unload_session ();
2093                 return -2;
2094         }
2095
2096         return 0;
2097 }
2098
2099 void
2100 ARDOUR_UI::setup_theme ()
2101 {
2102         theme_manager->setup_theme();
2103 }
2104
2105 void
2106 ARDOUR_UI::update_clocks ()
2107 {
2108         if (!editor || !editor->dragging_playhead()) {
2109                 Clock (_session->audible_frame(), false, editor->get_preferred_edit_position()); /* EMIT_SIGNAL */
2110         }
2111 }
2112
2113 void
2114 ARDOUR_UI::start_clocking ()
2115 {
2116         clock_signal_connection = RapidScreenUpdate.connect (sigc::mem_fun(*this, &ARDOUR_UI::update_clocks));
2117 }
2118
2119 void
2120 ARDOUR_UI::stop_clocking ()
2121 {
2122         clock_signal_connection.disconnect ();
2123 }
2124
2125 void
2126 ARDOUR_UI::toggle_clocking ()
2127 {
2128 #if 0
2129         if (clock_button.get_active()) {
2130                 start_clocking ();
2131         } else {
2132                 stop_clocking ();
2133         }
2134 #endif
2135 }
2136
2137 gint
2138 ARDOUR_UI::_blink (void *arg)
2139
2140 {
2141         ((ARDOUR_UI *) arg)->blink ();
2142         return TRUE;
2143 }
2144
2145 void
2146 ARDOUR_UI::blink ()
2147 {
2148         Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
2149 }
2150
2151 void
2152 ARDOUR_UI::start_blinking ()
2153 {
2154         /* Start the blink signal. Everybody with a blinking widget
2155            uses Blink to drive the widget's state.
2156         */
2157
2158         if (blink_timeout_tag < 0) {
2159                 blink_on = false;
2160                 blink_timeout_tag = g_timeout_add (240, _blink, this);
2161         }
2162 }
2163
2164 void
2165 ARDOUR_UI::stop_blinking ()
2166 {
2167         if (blink_timeout_tag >= 0) {
2168                 g_source_remove (blink_timeout_tag);
2169                 blink_timeout_tag = -1;
2170         }
2171 }
2172
2173
2174 /** Ask the user for the name of a new snapshot and then take it.
2175  */
2176
2177 void
2178 ARDOUR_UI::snapshot_session (bool switch_to_it)
2179 {
2180         ArdourPrompter prompter (true);
2181         string snapname;
2182
2183         prompter.set_name ("Prompter");
2184         prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2185         prompter.set_title (_("Take Snapshot"));
2186         prompter.set_prompt (_("Name of new snapshot"));
2187
2188         if (!switch_to_it) {
2189                 char timebuf[128];
2190                 time_t n;
2191                 struct tm local_time;
2192
2193                 time (&n);
2194                 localtime_r (&n, &local_time);
2195                 strftime (timebuf, sizeof(timebuf), "%FT%H.%M.%S", &local_time);
2196                 prompter.set_initial_text (timebuf);
2197         }
2198
2199   again:
2200         switch (prompter.run()) {
2201         case RESPONSE_ACCEPT:
2202         {
2203                 prompter.get_result (snapname);
2204
2205                 bool do_save = (snapname.length() != 0);
2206
2207                 if (do_save) {
2208                         char illegal = Session::session_name_is_legal(snapname);
2209                         if (illegal) {
2210                                 MessageDialog msg (string_compose (_("To ensure compatibility with various systems\n"
2211                                                      "snapshot names may not contain a '%1' character"), illegal));
2212                                 msg.run ();
2213                                 goto again;
2214                         }
2215                 }
2216
2217                 vector<sys::path> p;
2218                 get_state_files_in_directory (_session->session_directory().root_path(), p);
2219                 vector<string> n = get_file_names_no_extension (p);
2220                 if (find (n.begin(), n.end(), snapname) != n.end()) {
2221
2222                         ArdourDialog confirm (_("Confirm Snapshot Overwrite"), true);
2223                         Label m (_("A snapshot already exists with that name.  Do you want to overwrite it?"));
2224                         confirm.get_vbox()->pack_start (m, true, true);
2225                         confirm.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
2226                         confirm.add_button (_("Overwrite"), Gtk::RESPONSE_ACCEPT);
2227                         confirm.show_all ();
2228                         switch (confirm.run()) {
2229                         case RESPONSE_CANCEL:
2230                                 do_save = false;
2231                         }
2232                 }
2233
2234                 if (do_save) {
2235                         save_state (snapname, switch_to_it);
2236                 }
2237                 break;
2238         }
2239
2240         default:
2241                 break;
2242         }
2243 }
2244
2245 /** Ask the user for a new session name and then rename the session to it.
2246  */
2247
2248 void
2249 ARDOUR_UI::rename_session ()
2250 {
2251         if (!_session) {
2252                 return;
2253         }
2254
2255         ArdourPrompter prompter (true);
2256         string name;
2257
2258         prompter.set_name ("Prompter");
2259         prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2260         prompter.set_title (_("Rename Session"));
2261         prompter.set_prompt (_("New session name"));
2262
2263   again:
2264         switch (prompter.run()) {
2265         case RESPONSE_ACCEPT:
2266         {
2267                 prompter.get_result (name);
2268
2269                 bool do_rename = (name.length() != 0);
2270
2271                 if (do_rename) {
2272                         char illegal = Session::session_name_is_legal (name);
2273
2274                         if (illegal) {
2275                                 MessageDialog msg (string_compose (_("To ensure compatibility with various systems\n"
2276                                                                      "session names may not contain a '%1' character"), illegal));
2277                                 msg.run ();
2278                                 goto again;
2279                         }
2280
2281                         switch (_session->rename (name)) {
2282                         case -1: {
2283                                 MessageDialog msg (_("That name is already in use by another directory/folder. Please try again."));
2284                                 msg.set_position (WIN_POS_MOUSE);
2285                                 msg.run ();
2286                                 goto again;
2287                                 break;
2288                         }
2289                         case 0:
2290                                 break;
2291                         default: {
2292                                 MessageDialog msg (_("Renaming this session failed.\nThings could be seriously messed up at this point"));
2293                                 msg.set_position (WIN_POS_MOUSE);
2294                                 msg.run ();
2295                                 break;
2296                         }
2297                         }
2298                 }
2299                 
2300                 break;
2301         }
2302
2303         default:
2304                 break;
2305         }
2306 }
2307
2308 void
2309 ARDOUR_UI::save_state (const string & name, bool switch_to_it)
2310 {
2311         XMLNode* node = new XMLNode (X_("UI"));
2312
2313         for (list<WindowProxyBase*>::iterator i = _window_proxies.begin(); i != _window_proxies.end(); ++i) {
2314                 if (!(*i)->rc_configured()) {
2315                         node->add_child_nocopy (*((*i)->get_state ()));
2316                 }
2317         }
2318
2319         node->add_child_nocopy (gui_object_state->get_state());
2320
2321         _session->add_extra_xml (*node);
2322
2323         save_state_canfail (name, switch_to_it);
2324 }
2325
2326 int
2327 ARDOUR_UI::save_state_canfail (string name, bool switch_to_it)
2328 {
2329         if (_session) {
2330                 int ret;
2331
2332                 if (name.length() == 0) {
2333                         name = _session->snap_name();
2334                 }
2335
2336                 if ((ret = _session->save_state (name, false, switch_to_it)) != 0) {
2337                         return ret;
2338                 }
2339         }
2340
2341         save_ardour_state (); /* XXX cannot fail? yeah, right ... */
2342         return 0;
2343 }
2344
2345 void
2346 ARDOUR_UI::primary_clock_value_changed ()
2347 {
2348         if (_session) {
2349                 _session->request_locate (primary_clock->current_time ());
2350         }
2351 }
2352
2353 void
2354 ARDOUR_UI::big_clock_value_changed ()
2355 {
2356         if (_session) {
2357                 _session->request_locate (big_clock->current_time ());
2358         }
2359 }
2360
2361 void
2362 ARDOUR_UI::secondary_clock_value_changed ()
2363 {
2364         if (_session) {
2365                 _session->request_locate (secondary_clock->current_time ());
2366         }
2367 }
2368
2369 void
2370 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
2371 {
2372         if (_session == 0) {
2373                 return;
2374         }
2375
2376         if (_session->step_editing()) {
2377                 return;
2378         }
2379
2380         Session::RecordState const r = _session->record_status ();
2381         bool const h = _session->have_rec_enabled_track ();
2382
2383         if (r == Session::Enabled || (r == Session::Recording && !h)) {
2384                 if (onoff) {
2385                         rec_button.set_active_state (Active);
2386                 } else {
2387                         rec_button.set_active_state (Mid);
2388                 }
2389         } else if (r == Session::Recording && h) {
2390                 rec_button.set_active_state (Mid);
2391         } else {
2392                 rec_button.unset_active_state ();
2393         }
2394 }
2395
2396 void
2397 ARDOUR_UI::save_template ()
2398 {
2399         ArdourPrompter prompter (true);
2400         string name;
2401
2402         if (!check_audioengine()) {
2403                 return;
2404         }
2405
2406         prompter.set_name (X_("Prompter"));
2407         prompter.set_title (_("Save Template"));
2408         prompter.set_prompt (_("Name for template:"));
2409         prompter.set_initial_text(_session->name() + _("-template"));
2410         prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2411
2412         switch (prompter.run()) {
2413         case RESPONSE_ACCEPT:
2414                 prompter.get_result (name);
2415
2416                 if (name.length()) {
2417                         _session->save_template (name);
2418                 }
2419                 break;
2420
2421         default:
2422                 break;
2423         }
2424 }
2425
2426 void
2427 ARDOUR_UI::edit_metadata ()
2428 {
2429         SessionMetadataEditor dialog;
2430         dialog.set_session (_session);
2431         editor->ensure_float (dialog);
2432         dialog.run ();
2433 }
2434
2435 void
2436 ARDOUR_UI::import_metadata ()
2437 {
2438         SessionMetadataImporter dialog;
2439         dialog.set_session (_session);
2440         editor->ensure_float (dialog);
2441         dialog.run ();
2442 }
2443
2444 bool
2445 ARDOUR_UI::ask_about_loading_existing_session (const std::string& session_path)
2446 {
2447         std::string str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2448
2449         MessageDialog msg (str,
2450                            false,
2451                            Gtk::MESSAGE_WARNING,
2452                            Gtk::BUTTONS_YES_NO,
2453                            true);
2454
2455
2456         msg.set_name (X_("OpenExistingDialog"));
2457         msg.set_title (_("Open Existing Session"));
2458         msg.set_wmclass (X_("existing_session"), PROGRAM_NAME);
2459         msg.set_position (Gtk::WIN_POS_MOUSE);
2460         pop_back_splash ();
2461
2462         switch (msg.run()) {
2463         case RESPONSE_YES:
2464                 return true;
2465                 break;
2466         }
2467         return false;
2468 }
2469
2470 int
2471 ARDOUR_UI::build_session_from_nsd (const std::string& session_path, const std::string& session_name)
2472 {
2473         BusProfile bus_profile;
2474
2475         if (Profile->get_sae()) {
2476
2477                 bus_profile.master_out_channels = 2;
2478                 bus_profile.input_ac = AutoConnectPhysical;
2479                 bus_profile.output_ac = AutoConnectMaster;
2480                 bus_profile.requested_physical_in = 0; // use all available
2481                 bus_profile.requested_physical_out = 0; // use all available
2482
2483         } else {
2484
2485                 /* get settings from advanced section of NSD */
2486
2487                 if (_startup->create_master_bus()) {
2488                         bus_profile.master_out_channels = (uint32_t) _startup->master_channel_count();
2489                 } else {
2490                         bus_profile.master_out_channels = 0;
2491                 }
2492
2493                 if (_startup->connect_inputs()) {
2494                         bus_profile.input_ac = AutoConnectPhysical;
2495                 } else {
2496                         bus_profile.input_ac = AutoConnectOption (0);
2497                 }
2498
2499                 bus_profile.output_ac = AutoConnectOption (0);
2500
2501                 if (_startup->connect_outputs ()) {
2502                         if (_startup->connect_outs_to_master()) {
2503                                 bus_profile.output_ac = AutoConnectMaster;
2504                         } else if (_startup->connect_outs_to_physical()) {
2505                                 bus_profile.output_ac = AutoConnectPhysical;
2506                         }
2507                 }
2508
2509                 bus_profile.requested_physical_in = (uint32_t) _startup->input_limit_count();
2510                 bus_profile.requested_physical_out = (uint32_t) _startup->output_limit_count();
2511         }
2512
2513         if (build_session (session_path, session_name, bus_profile)) {
2514                 return -1;
2515         }
2516
2517         return 0;
2518 }
2519
2520 void
2521 ARDOUR_UI::idle_load (const std::string& path)
2522 {
2523         if (_session) {
2524                 if (Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
2525                         /* /path/to/foo => /path/to/foo, foo */
2526                         load_session (path, basename_nosuffix (path));
2527                 } else {
2528                         /* /path/to/foo/foo.ardour => /path/to/foo, foo */
2529                         load_session (Glib::path_get_dirname (path), basename_nosuffix (path));
2530                 }
2531         } else {
2532
2533                 ARDOUR_COMMAND_LINE::session_name = path;
2534
2535                 /*
2536                  * new_session_dialog doens't exist in A3
2537                  * Try to remove all references to it to
2538                  * see if it will compile.  NOTE: this will
2539                  * likely cause a runtime issue is my somewhat
2540                  * uneducated guess.
2541                  */
2542
2543                 //if (new_session_dialog) {
2544
2545
2546                         /* make it break out of Dialog::run() and
2547                            start again.
2548                          */
2549
2550                         //new_session_dialog->response (1);
2551                 //}
2552         }
2553 }
2554
2555 void
2556 ARDOUR_UI::end_loading_messages ()
2557 {
2558         // hide_splash ();
2559 }
2560
2561 void
2562 ARDOUR_UI::loading_message (const std::string& /*msg*/)
2563 {
2564         // show_splash ();
2565         // splash->message (msg);
2566         flush_pending ();
2567 }
2568
2569 /** @param quit_on_cancel true if exit() should be called if the user clicks `cancel' in the new session dialog */
2570 int
2571 ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new, string load_template)
2572 {
2573         string session_name;
2574         string session_path;
2575         string template_name;
2576         int ret = -1;
2577         bool likely_new = false;
2578
2579         if (!load_template.empty()) {
2580                 should_be_new = true;
2581                 template_name = load_template;
2582         }
2583
2584         while (ret != 0) {
2585
2586                 if (!should_be_new && !ARDOUR_COMMAND_LINE::session_name.empty()) {
2587
2588                         /* if they named a specific statefile, use it, otherwise they are
2589                            just giving a session folder, and we want to use it as is
2590                            to find the session.
2591                         */
2592
2593                         string::size_type suffix = ARDOUR_COMMAND_LINE::session_name.find (statefile_suffix);
2594
2595                         if (suffix != string::npos) {
2596                                 session_path = Glib::path_get_dirname (ARDOUR_COMMAND_LINE::session_name);
2597                                 session_name = ARDOUR_COMMAND_LINE::session_name.substr (0, suffix);
2598                                 session_name = Glib::path_get_basename (session_name);
2599                         } else {
2600                                 session_path = ARDOUR_COMMAND_LINE::session_name;
2601                                 session_name = Glib::path_get_basename (ARDOUR_COMMAND_LINE::session_name);
2602                         }
2603
2604                 } else {
2605
2606                         bool const apply = run_startup (should_be_new, load_template);
2607
2608                         if (!apply) {
2609                                 if (quit_on_cancel) {
2610                                         exit (1);
2611                                 } else {
2612                                         return ret;
2613                                 }
2614                         }
2615
2616                         /* if we run the startup dialog again, offer more than just "new session" */
2617
2618                         should_be_new = false;
2619
2620                         session_name = _startup->session_name (likely_new);
2621
2622                         string::size_type suffix = session_name.find (statefile_suffix);
2623
2624                         if (suffix != string::npos) {
2625                                 session_name = session_name.substr (0, suffix);
2626                         }
2627
2628                         /* this shouldn't happen, but we catch it just in case it does */
2629
2630                         if (session_name.empty()) {
2631                                 continue;
2632                         }
2633
2634                         if (_startup->use_session_template()) {
2635                                 template_name = _startup->session_template_name();
2636                                 _session_is_new = true;
2637                         }
2638
2639                         if (session_name[0] == G_DIR_SEPARATOR ||
2640                             (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == G_DIR_SEPARATOR) ||
2641                             (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == G_DIR_SEPARATOR)) {
2642
2643                                 /* absolute path or cwd-relative path specified for session name: infer session folder
2644                                    from what was given.
2645                                 */
2646
2647                                 session_path = Glib::path_get_dirname (session_name);
2648                                 session_name = Glib::path_get_basename (session_name);
2649
2650                         } else {
2651
2652                                 session_path = _startup->session_folder();
2653
2654                                 char illegal = Session::session_name_is_legal (session_name);
2655
2656                                 if (illegal) {
2657                                         MessageDialog msg (*_startup,
2658                                                            string_compose (_("To ensure compatibility with various systems\n"
2659                                                                              "session names may not contain a '%1' character"),
2660                                                                            illegal));
2661                                         msg.run ();
2662                                         ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2663                                         continue;
2664                                 }
2665                         }
2666                 }
2667
2668                 if (create_engine ()) {
2669                         break;
2670                 }
2671
2672                 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2673
2674                         if (likely_new) {
2675
2676                                 std::string existing = Glib::build_filename (session_path, session_name);
2677
2678                                 if (!ask_about_loading_existing_session (existing)) {
2679                                         ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2680                                         continue;
2681                                 }
2682                         }
2683
2684                         _session_is_new = false;
2685
2686                 } else {
2687
2688                         if (!likely_new) {
2689                                 MessageDialog msg (string_compose (_("There is no existing session at \"%1\""), session_path));
2690                                 msg.run ();
2691                                 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2692                                 continue;
2693                         }
2694
2695                         if (session_name.find ('/') != std::string::npos) {
2696                                 MessageDialog msg (*_startup,
2697                                                    _("To ensure compatibility with various systems\n"
2698                                                      "session names may not contain a '/' character"));
2699                                 msg.run ();
2700                                 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2701                                 continue;
2702                         }
2703
2704                         if (session_name.find ('\\') != std::string::npos) {
2705                                 MessageDialog msg (*_startup,
2706                                                    _("To ensure compatibility with various systems\n"
2707                                                      "session names may not contain a '\\' character"));
2708                                 msg.run ();
2709                                 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2710                                 continue;
2711                         }
2712
2713                         _session_is_new = true;
2714                 }
2715
2716                 if (likely_new && template_name.empty()) {
2717
2718                         ret = build_session_from_nsd (session_path, session_name);
2719
2720                 } else {
2721
2722                         ret = load_session (session_path, session_name, template_name);
2723
2724                         if (ret == -2) {
2725                                 /* not connected to the AudioEngine, so quit to avoid an infinite loop */
2726                                 exit (1);
2727                         }
2728
2729                         if (!ARDOUR_COMMAND_LINE::immediate_save.empty()) {
2730                                 _session->save_state (ARDOUR_COMMAND_LINE::immediate_save, false);
2731                                 exit (1);
2732                         }
2733                 }
2734         }
2735
2736         return ret;
2737 }
2738
2739 void
2740 ARDOUR_UI::close_session()
2741 {
2742         if (!check_audioengine()) {
2743                 return;
2744         }
2745
2746         if (unload_session (true)) {
2747                 return;
2748         }
2749
2750         ARDOUR_COMMAND_LINE::session_name = "";
2751
2752         if (get_session_parameters (true, false)) {
2753                 exit (1);
2754         }
2755
2756         goto_editor_window ();
2757 }
2758
2759 /** @param snap_name Snapshot name (without .ardour suffix).
2760  *  @return -2 if the load failed because we are not connected to the AudioEngine.
2761  */
2762 int
2763 ARDOUR_UI::load_session (const std::string& path, const std::string& snap_name, std::string mix_template)
2764 {
2765         Session *new_session;
2766         int unload_status;
2767         int retval = -1;
2768
2769         session_loaded = false;
2770
2771         if (!check_audioengine()) {
2772                 return -2;
2773         }
2774
2775         unload_status = unload_session ();
2776
2777         if (unload_status < 0) {
2778                 goto out;
2779         } else if (unload_status > 0) {
2780                 retval = 0;
2781                 goto out;
2782         }
2783
2784         loading_message (string_compose (_("Please wait while %1 loads your session"), PROGRAM_NAME));
2785
2786         try {
2787                 new_session = new Session (*engine, path, snap_name, 0, mix_template);
2788         }
2789
2790         /* this one is special */
2791
2792         catch (AudioEngine::PortRegistrationFailure& err) {
2793
2794                 MessageDialog msg (err.what(),
2795                                    true,
2796                                    Gtk::MESSAGE_INFO,
2797                                    Gtk::BUTTONS_CLOSE);
2798
2799                 msg.set_title (_("Port Registration Error"));
2800                 msg.set_secondary_text (_("Click the Close button to try again."));
2801                 msg.set_position (Gtk::WIN_POS_CENTER);
2802                 pop_back_splash ();
2803                 msg.present ();
2804
2805                 int response = msg.run ();
2806
2807                 msg.hide ();
2808
2809                 switch (response) {
2810                 case RESPONSE_CANCEL:
2811                         exit (1);
2812                 default:
2813                         break;
2814                 }
2815                 goto out;
2816         }
2817
2818         catch (...) {
2819
2820                 MessageDialog msg (string_compose(
2821                                            _("Session \"%1 (snapshot %2)\" did not load successfully"),
2822                                            path, snap_name),
2823                                    true,
2824                                    Gtk::MESSAGE_INFO,
2825                                    BUTTONS_OK);
2826
2827                 msg.set_title (_("Loading Error"));
2828                 msg.set_secondary_text (_("Click the Refresh button to try again."));
2829                 msg.add_button (Stock::REFRESH, 1);
2830                 msg.set_position (Gtk::WIN_POS_CENTER);
2831                 pop_back_splash ();
2832                 msg.present ();
2833
2834                 int response = msg.run ();
2835
2836                 switch (response) {
2837                 case 1:
2838                         break;
2839                 default:
2840                         exit (1);
2841                 }
2842
2843                 msg.hide ();
2844
2845                 goto out;
2846         }
2847
2848         {
2849                 list<string> const u = new_session->unknown_processors ();
2850                 if (!u.empty()) {
2851                         MissingPluginDialog d (_session, u);
2852                         d.run ();
2853                 }
2854         }
2855
2856         /* Now the session been created, add the transport controls */
2857         new_session->add_controllable(roll_controllable);
2858         new_session->add_controllable(stop_controllable);
2859         new_session->add_controllable(goto_start_controllable);
2860         new_session->add_controllable(goto_end_controllable);
2861         new_session->add_controllable(auto_loop_controllable);
2862         new_session->add_controllable(play_selection_controllable);
2863         new_session->add_controllable(rec_controllable);
2864
2865         set_session (new_session);
2866
2867         session_loaded = true;
2868
2869         goto_editor_window ();
2870
2871         if (_session) {
2872                 _session->set_clean ();
2873         }
2874
2875         flush_pending ();
2876         retval = 0;
2877
2878   out:
2879         return retval;
2880 }
2881
2882 int
2883 ARDOUR_UI::build_session (const std::string& path, const std::string& snap_name, BusProfile& bus_profile)
2884 {
2885         Session *new_session;
2886         int x;
2887
2888         if (!check_audioengine()) {
2889                 return -1;
2890         }
2891
2892         session_loaded = false;
2893
2894         x = unload_session ();
2895
2896         if (x < 0) {
2897                 return -1;
2898         } else if (x > 0) {
2899                 return 0;
2900         }
2901
2902         _session_is_new = true;
2903
2904         try {
2905                 new_session = new Session (*engine, path, snap_name, &bus_profile);
2906         }
2907
2908         catch (...) {
2909
2910                 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2911                 pop_back_splash ();
2912                 msg.run ();
2913                 return -1;
2914         }
2915
2916         /* Give the new session the default GUI state, if such things exist */
2917
2918         XMLNode* n;
2919         n = Config->instant_xml (X_("Editor"));
2920         if (n) {
2921                 new_session->add_instant_xml (*n, false);
2922         }
2923         n = Config->instant_xml (X_("Mixer"));
2924         if (n) {
2925                 new_session->add_instant_xml (*n, false);
2926         }
2927
2928         /* Put the playhead at 0 and scroll fully left */
2929         n = new_session->instant_xml (X_("Editor"));
2930         if (n) {
2931                 n->add_property (X_("playhead"), X_("0"));
2932                 n->add_property (X_("left-frame"), X_("0"));
2933         }
2934
2935         set_session (new_session);
2936
2937         session_loaded = true;
2938
2939         new_session->save_state(new_session->name());
2940
2941         return 0;
2942 }
2943
2944 void
2945 ARDOUR_UI::launch_chat ()
2946 {
2947 #ifdef __APPLE__
2948         open_uri("http://webchat.freenode.net/?channels=ardour-osx");
2949 #else
2950         open_uri("http://webchat.freenode.net/?channels=ardour");
2951 #endif
2952 }
2953
2954 void
2955 ARDOUR_UI::show_about ()
2956 {
2957         if (about == 0) {
2958                 about = new About;
2959                 about->signal_response().connect(sigc::mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2960         }
2961
2962         about->set_transient_for(*editor);
2963         about->show_all ();
2964 }
2965
2966 void
2967 ARDOUR_UI::launch_manual ()
2968 {
2969         PBD::open_uri("http://ardour.org/flossmanual");
2970 }
2971
2972 void
2973 ARDOUR_UI::launch_reference ()
2974 {
2975         PBD::open_uri("http://ardour.org/refmanual");
2976 }
2977
2978 void
2979 ARDOUR_UI::hide_about ()
2980 {
2981         if (about) {
2982                 about->get_window()->set_cursor ();
2983                 about->hide ();
2984         }
2985 }
2986
2987 void
2988 ARDOUR_UI::about_signal_response (int /*response*/)
2989 {
2990         hide_about();
2991 }
2992
2993 void
2994 ARDOUR_UI::show_splash ()
2995 {
2996         if (splash == 0) {
2997                 try {
2998                         splash = new Splash;
2999                 } catch (...) {
3000                         return;
3001                 }
3002         }
3003
3004         splash->show ();
3005         splash->present ();
3006         splash->queue_draw ();
3007         splash->get_window()->process_updates (true);
3008         flush_pending ();
3009 }
3010
3011 void
3012 ARDOUR_UI::hide_splash ()
3013 {
3014         if (splash) {
3015                 splash->hide();
3016         }
3017 }
3018
3019 void
3020 ARDOUR_UI::display_cleanup_results (ARDOUR::CleanupReport& rep, const gchar* list_title,
3021                                     const string& plural_msg, const string& singular_msg)
3022 {
3023         size_t removed;
3024
3025         removed = rep.paths.size();
3026
3027         if (removed == 0) {
3028                 MessageDialog msgd (*editor,
3029                                     _("No files were ready for clean-up"),
3030                                     true,
3031                                     Gtk::MESSAGE_INFO,
3032                                     Gtk::BUTTONS_OK);
3033                 msgd.set_title (_("Clean-up"));
3034                 msgd.set_secondary_text (_("If this seems suprising, \n\
3035 check for any existing snapshots.\n\
3036 These may still include regions that\n\
3037 require some unused files to continue to exist."));
3038
3039                 msgd.run ();
3040                 return;
3041         }
3042
3043         ArdourDialog results (_("Clean-up"), true, false);
3044
3045         struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
3046             CleanupResultsModelColumns() {
3047                     add (visible_name);
3048                     add (fullpath);
3049             }
3050             Gtk::TreeModelColumn<std::string> visible_name;
3051             Gtk::TreeModelColumn<std::string> fullpath;
3052         };
3053
3054
3055         CleanupResultsModelColumns results_columns;
3056         Glib::RefPtr<Gtk::ListStore> results_model;
3057         Gtk::TreeView results_display;
3058
3059         results_model = ListStore::create (results_columns);
3060         results_display.set_model (results_model);
3061         results_display.append_column (list_title, results_columns.visible_name);
3062
3063         results_display.set_name ("CleanupResultsList");
3064         results_display.set_headers_visible (true);
3065         results_display.set_headers_clickable (false);
3066         results_display.set_reorderable (false);
3067
3068         Gtk::ScrolledWindow list_scroller;
3069         Gtk::Label txt;
3070         Gtk::VBox dvbox;
3071         Gtk::HBox dhbox;  // the hbox for the image and text
3072         Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
3073         Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO,  Gtk::ICON_SIZE_DIALOG));
3074
3075         dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
3076
3077         const string dead_directory = _session->session_directory().dead_path().to_string();
3078
3079         /* subst:
3080            %1 - number of files removed
3081            %2 - location of "dead"
3082            %3 - size of files affected
3083            %4 - prefix for "bytes" to produce sensible results (e.g. mega, kilo, giga)
3084         */
3085
3086         const char* bprefix;
3087         double space_adjusted = 0;
3088
3089         if (rep.space < 1000) {
3090                 bprefix = X_("");
3091                 space_adjusted = rep.space;
3092         } else if (rep.space < 1000000) {
3093                 bprefix = X_("kilo");
3094                 space_adjusted = truncf((float)rep.space / 1000.0);
3095         } else if (rep.space < 1000000 * 1000) {
3096                 bprefix = X_("mega");
3097                 space_adjusted = truncf((float)rep.space / (1000.0 * 1000.0));
3098         } else {
3099                 bprefix = X_("giga");
3100                 space_adjusted = truncf((float)rep.space / (1000.0 * 1000 * 1000.0));
3101         }
3102
3103         if (removed > 1) {
3104                 txt.set_text (string_compose (plural_msg, removed, dead_directory, space_adjusted, bprefix));
3105         } else {
3106                 txt.set_text (string_compose (singular_msg, removed, dead_directory, space_adjusted, bprefix));
3107         }
3108
3109         dhbox.pack_start (*dimage, true, false, 5);
3110         dhbox.pack_start (txt, true, false, 5);
3111
3112         for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
3113                 TreeModel::Row row = *(results_model->append());
3114                 row[results_columns.visible_name] = *i;
3115                 row[results_columns.fullpath] = *i;
3116         }
3117
3118         list_scroller.add (results_display);
3119         list_scroller.set_size_request (-1, 150);
3120         list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
3121
3122         dvbox.pack_start (dhbox, true, false, 5);
3123         dvbox.pack_start (list_scroller, true, false, 5);
3124         ddhbox.pack_start (dvbox, true, false, 5);
3125
3126         results.get_vbox()->pack_start (ddhbox, true, false, 5);
3127         results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
3128         results.set_default_response (RESPONSE_CLOSE);
3129         results.set_position (Gtk::WIN_POS_MOUSE);
3130
3131         results_display.show();
3132         list_scroller.show();
3133         txt.show();
3134         dvbox.show();
3135         dhbox.show();
3136         ddhbox.show();
3137         dimage->show();
3138
3139         //results.get_vbox()->show();
3140         results.set_resizable (false);
3141
3142         results.run ();
3143
3144 }
3145
3146 void
3147 ARDOUR_UI::cleanup ()
3148 {
3149         if (_session == 0) {
3150                 /* shouldn't happen: menu item is insensitive */
3151                 return;
3152         }
3153
3154
3155         MessageDialog checker (_("Are you sure you want to clean-up?"),
3156                                 true,
3157                                 Gtk::MESSAGE_QUESTION,
3158                                 Gtk::BUTTONS_NONE);
3159
3160         checker.set_title (_("Clean-up"));
3161
3162         checker.set_secondary_text(_("Clean-up is a destructive operation.\n\
3163 ALL undo/redo information will be lost if you clean-up.\n\
3164 Clean-up will move all unused files to a \"dead\" location."));
3165
3166         checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
3167         checker.add_button (_("Clean-up"), RESPONSE_ACCEPT);
3168         checker.set_default_response (RESPONSE_CANCEL);
3169
3170         checker.set_name (_("CleanupDialog"));
3171         checker.set_wmclass (X_("ardour_cleanup"), PROGRAM_NAME);
3172         checker.set_position (Gtk::WIN_POS_MOUSE);
3173
3174         switch (checker.run()) {
3175         case RESPONSE_ACCEPT:
3176                 break;
3177         default:
3178                 return;
3179         }
3180
3181         ARDOUR::CleanupReport rep;
3182
3183         editor->prepare_for_cleanup ();
3184
3185         /* do not allow flush until a session is reloaded */
3186
3187         Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
3188         if (act) {
3189                 act->set_sensitive (false);
3190         }
3191
3192         if (_session->cleanup_sources (rep)) {
3193                 editor->finish_cleanup ();
3194                 return;
3195         }
3196
3197         editor->finish_cleanup ();
3198
3199         checker.hide();
3200         display_cleanup_results (rep,
3201                                  _("Cleaned Files"),
3202                                  _("\
3203 The following %1 files were not in use and \n\
3204 have been moved to:\n\n\
3205 %2\n\n\
3206 After a restart of Ardour,\n\n\
3207 Session -> Clean-up -> Flush Wastebasket\n\n\
3208 will release an additional\n\
3209 %3 %4bytes of disk space.\n"),
3210                                  _("\
3211 The following file was not in use and \n\
3212 has been moved to:\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
3220 }
3221
3222 void
3223 ARDOUR_UI::flush_trash ()
3224 {
3225         if (_session == 0) {
3226                 /* shouldn't happen: menu item is insensitive */
3227                 return;
3228         }
3229
3230         ARDOUR::CleanupReport rep;
3231
3232         if (_session->cleanup_trash_sources (rep)) {
3233                 return;
3234         }
3235
3236         display_cleanup_results (rep,
3237                                  _("deleted file"),
3238                                  _("The following %1 files were deleted from\n\
3239 %2,\n\
3240 releasing %3 %4bytes of disk space"),
3241                                  _("The following file was deleted from\n\
3242 %2,\n\
3243 releasing %3 %4bytes of disk space"));
3244 }
3245
3246 void
3247 ARDOUR_UI::add_route (Gtk::Window* float_window)
3248 {
3249         int count;
3250
3251         if (!_session) {
3252                 return;
3253         }
3254
3255         if (add_route_dialog == 0) {
3256                 add_route_dialog = new AddRouteDialog (_session);
3257                 if (float_window) {
3258                         add_route_dialog->set_transient_for (*float_window);
3259                 }
3260         }
3261
3262         if (add_route_dialog->is_visible()) {
3263                 /* we're already doing this */
3264                 return;
3265         }
3266
3267         ResponseType r = (ResponseType) add_route_dialog->run ();
3268
3269         add_route_dialog->hide();
3270
3271         switch (r) {
3272                 case RESPONSE_ACCEPT:
3273                         break;
3274                 default:
3275                         return;
3276                         break;
3277         }
3278
3279         if ((count = add_route_dialog->count()) <= 0) {
3280                 return;
3281         }
3282
3283         string template_path = add_route_dialog->track_template();
3284
3285         if (!template_path.empty()) {
3286                 _session->new_route_from_template (count, template_path);
3287                 return;
3288         }
3289
3290         uint32_t input_chan = add_route_dialog->channels ();
3291         uint32_t output_chan;
3292         string name_template = add_route_dialog->name_template ();
3293         bool track = add_route_dialog->track ();
3294         RouteGroup* route_group = add_route_dialog->route_group ();
3295
3296         AutoConnectOption oac = Config->get_output_auto_connect();
3297
3298         if (oac & AutoConnectMaster) {
3299                 output_chan = (_session->master_out() ? _session->master_out()->n_inputs().n_audio() : input_chan);
3300         } else {
3301                 output_chan = input_chan;
3302         }
3303
3304         /* XXX do something with name template */
3305
3306         if (add_route_dialog->type() == ARDOUR::DataType::MIDI) {
3307                 if (track) {
3308                         session_add_midi_track (route_group, count, name_template);
3309                 } else  {
3310                         MessageDialog msg (*editor,
3311                                         _("Sorry, MIDI Busses are not supported at this time."));
3312                         msg.run ();
3313                         //session_add_midi_bus();
3314                 }
3315         } else {
3316                 if (track) {
3317                         session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), route_group, count, name_template);
3318                 } else {
3319                         session_add_audio_bus (input_chan, output_chan, route_group, count, name_template);
3320                 }
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 }