59196c75abcdec151da80efbfa5e697c56ff0349
[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                 ProcessorEntry::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 (Gtk::Window& win)
511 {
512         if (Splash::instance()) {
513                 Splash::instance()->pop_back_for (win);
514         }
515 }
516
517 gint
518 ARDOUR_UI::configure_timeout ()
519 {
520         if (last_configure_time == 0) {
521                 /* no configure events yet */
522                 return true;
523         }
524
525         /* force a gap of 0.5 seconds since the last configure event
526          */
527
528         if (get_microseconds() - last_configure_time < 500000) {
529                 return true;
530         } else {
531                 have_configure_timeout = false;
532                 cerr << "config event-driven save\n";
533                 save_ardour_state ();
534                 return false;
535         }
536 }
537
538 gboolean
539 ARDOUR_UI::configure_handler (GdkEventConfigure* /*conf*/)
540 {
541         if (have_configure_timeout) {
542                 last_configure_time = get_microseconds();
543         } else {
544                 Glib::signal_timeout().connect (sigc::mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
545                 have_configure_timeout = true;
546         }
547
548         return FALSE;
549 }
550
551 void
552 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
553 {
554         const XMLProperty* prop;
555
556         if ((prop = node.property ("roll")) != 0) {
557                 roll_controllable->set_id (prop->value());
558         }
559         if ((prop = node.property ("stop")) != 0) {
560                 stop_controllable->set_id (prop->value());
561         }
562         if ((prop = node.property ("goto-start")) != 0) {
563                 goto_start_controllable->set_id (prop->value());
564         }
565         if ((prop = node.property ("goto-end")) != 0) {
566                 goto_end_controllable->set_id (prop->value());
567         }
568         if ((prop = node.property ("auto-loop")) != 0) {
569                 auto_loop_controllable->set_id (prop->value());
570         }
571         if ((prop = node.property ("play-selection")) != 0) {
572                 play_selection_controllable->set_id (prop->value());
573         }
574         if ((prop = node.property ("rec")) != 0) {
575                 rec_controllable->set_id (prop->value());
576         }
577         if ((prop = node.property ("shuttle")) != 0) {
578                 shuttle_box->controllable()->set_id (prop->value());
579         }
580
581 }
582
583 XMLNode&
584 ARDOUR_UI::get_transport_controllable_state ()
585 {
586         XMLNode* node = new XMLNode(X_("TransportControllables"));
587         char buf[64];
588
589         roll_controllable->id().print (buf, sizeof (buf));
590         node->add_property (X_("roll"), buf);
591         stop_controllable->id().print (buf, sizeof (buf));
592         node->add_property (X_("stop"), buf);
593         goto_start_controllable->id().print (buf, sizeof (buf));
594         node->add_property (X_("goto_start"), buf);
595         goto_end_controllable->id().print (buf, sizeof (buf));
596         node->add_property (X_("goto_end"), buf);
597         auto_loop_controllable->id().print (buf, sizeof (buf));
598         node->add_property (X_("auto_loop"), buf);
599         play_selection_controllable->id().print (buf, sizeof (buf));
600         node->add_property (X_("play_selection"), buf);
601         rec_controllable->id().print (buf, sizeof (buf));
602         node->add_property (X_("rec"), buf);
603         shuttle_box->controllable()->id().print (buf, sizeof (buf));
604         node->add_property (X_("shuttle"), buf);
605
606         return *node;
607 }
608
609
610 gint
611 ARDOUR_UI::autosave_session ()
612 {
613         if (g_main_depth() > 1) {
614                 /* inside a recursive main loop,
615                    give up because we may not be able to
616                    take a lock.
617                 */
618                 return 1;
619         }
620
621         if (!Config->get_periodic_safety_backups()) {
622                 return 1;
623         }
624
625         if (_session) {
626                 _session->maybe_write_autosave();
627         }
628
629         return 1;
630 }
631
632 void
633 ARDOUR_UI::update_autosave ()
634 {
635         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::update_autosave)
636
637         if (_session && _session->dirty()) {
638                 if (_autosave_connection.connected()) {
639                         _autosave_connection.disconnect();
640                 }
641
642                 _autosave_connection = Glib::signal_timeout().connect (sigc::mem_fun (*this, &ARDOUR_UI::autosave_session),
643                                 Config->get_periodic_safety_backup_interval() * 1000);
644
645         } else {
646                 if (_autosave_connection.connected()) {
647                         _autosave_connection.disconnect();
648                 }
649         }
650 }
651
652 void
653 ARDOUR_UI::backend_audio_error (bool we_set_params, Gtk::Window* toplevel)
654 {
655         string title;
656         if (we_set_params) {
657                 title = string_compose (_("%1 could not start JACK"), PROGRAM_NAME);
658         } else {
659                 title = string_compose (_("%1 could not connect to JACK."), PROGRAM_NAME);
660         }
661
662         MessageDialog win (title,
663                            false,
664                            Gtk::MESSAGE_INFO,
665                            Gtk::BUTTONS_NONE);
666
667         if (we_set_params) {
668                 win.set_secondary_text(_("There are several possible reasons:\n\
669 \n\
670 1) You requested audio parameters that are not supported..\n\
671 2) JACK is running as another user.\n\
672 \n\
673 Please consider the possibilities, and perhaps try different parameters."));
674         } else {
675                 win.set_secondary_text(_("There are several possible reasons:\n\
676 \n\
677 1) JACK is not running.\n\
678 2) JACK is running as another user, perhaps root.\n\
679 3) There is already another client called \"ardour\".\n\
680 \n\
681 Please consider the possibilities, and perhaps (re)start JACK."));
682         }
683
684         if (toplevel) {
685                 win.set_transient_for (*toplevel);
686         }
687
688         if (we_set_params) {
689                 win.add_button (Stock::OK, RESPONSE_CLOSE);
690         } else {
691                 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
692         }
693
694         win.set_default_response (RESPONSE_CLOSE);
695
696         win.show_all ();
697         win.set_position (Gtk::WIN_POS_CENTER);
698         pop_back_splash (win);
699
700         /* we just don't care about the result, but we want to block */
701
702         win.run ();
703 }
704
705 void
706 ARDOUR_UI::startup ()
707 {
708         Application* app = Application::instance ();
709
710         app->ShouldQuit.connect (sigc::mem_fun (*this, &ARDOUR_UI::queue_finish));
711         app->ShouldLoad.connect (sigc::mem_fun (*this, &ARDOUR_UI::idle_load));
712
713 #ifdef PHONE_HOME
714         call_the_mothership (VERSIONSTRING);
715 #endif
716
717         app->ready ();
718
719         if (get_session_parameters (true, ARDOUR_COMMAND_LINE::new_session, ARDOUR_COMMAND_LINE::load_template)) {
720                 exit (1);
721         }
722
723         use_config ();
724
725         goto_editor_window ();
726
727         /* Add the window proxies here; their addition may cause windows to be opened, and we want them
728            to be opened on top of the editor window that goto_editor_window() just opened.
729         */
730         add_window_proxy (location_ui);
731         add_window_proxy (big_clock_window);
732         for (ARDOUR::DataType::iterator i = ARDOUR::DataType::begin(); i != ARDOUR::DataType::end(); ++i) {
733                 add_window_proxy (_global_port_matrix[*i]);
734         }
735
736         /* We have to do this here since goto_editor_window() ends up calling show_all() on the
737          * editor window, and we may want stuff to be hidden.
738          */
739         _status_bar_visibility.update ();
740
741         BootMessage (string_compose (_("%1 is ready for use"), PROGRAM_NAME));
742 }
743
744 void
745 ARDOUR_UI::no_memory_warning ()
746 {
747         XMLNode node (X_("no-memory-warning"));
748         Config->add_instant_xml (node);
749 }
750
751 void
752 ARDOUR_UI::check_memory_locking ()
753 {
754 #ifdef __APPLE__
755         /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
756         return;
757 #else // !__APPLE__
758
759         XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"));
760
761         if (engine->is_realtime() && memory_warning_node == 0) {
762
763                 struct rlimit limits;
764                 int64_t ram;
765                 long pages, page_size;
766
767                 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
768                         ram = 0;
769                 } else {
770                         ram = (int64_t) pages * (int64_t) page_size;
771                 }
772
773                 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
774                         return;
775                 }
776
777                 if (limits.rlim_cur != RLIM_INFINITY) {
778
779                         if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
780
781                                 MessageDialog msg (
782                                         string_compose (
783                                                 _("WARNING: Your system has a limit for maximum amount of locked memory. "
784                                                   "This might cause %1 to run out of memory before your system "
785                                                   "runs out of memory. \n\n"
786                                                   "You can view the memory limit with 'ulimit -l', "
787                                                   "and it is normally controlled by /etc/security/limits.conf"),
788                                                 PROGRAM_NAME).c_str());
789
790                                 VBox* vbox = msg.get_vbox();
791                                 HBox hbox;
792                                 CheckButton cb (_("Do not show this window again"));
793
794                                 cb.signal_toggled().connect (sigc::mem_fun (*this, &ARDOUR_UI::no_memory_warning));
795
796                                 hbox.pack_start (cb, true, false);
797                                 vbox->pack_start (hbox);
798                                 cb.show();
799                                 vbox->show();
800                                 hbox.show ();
801
802                                 pop_back_splash (msg);
803
804                                 editor->ensure_float (msg);
805                                 msg.run ();
806                         }
807                 }
808         }
809 #endif // !__APPLE__
810 }
811
812
813 void
814 ARDOUR_UI::queue_finish ()
815 {
816         Glib::signal_idle().connect (mem_fun (*this, &ARDOUR_UI::idle_finish));
817 }
818
819 bool
820 ARDOUR_UI::idle_finish ()
821 {
822         finish ();
823         return false; /* do not call again */
824 }
825
826 void
827 ARDOUR_UI::finish()
828 {
829         if (_session) {
830                 int tries = 0;
831
832                 if (_session->transport_rolling() && (++tries < 8)) {
833                         _session->request_stop (false, true);
834                         usleep (10000);
835                 }
836
837                 if (_session->dirty()) {
838                         vector<string> actions;
839                         actions.push_back (_("Don't quit"));
840                         actions.push_back (_("Just quit"));
841                         actions.push_back (_("Save and quit"));
842                         switch (ask_about_saving_session(actions)) {
843                         case -1:
844                                 return;
845                                 break;
846                         case 1:
847                                 /* use the default name */
848                                 if (save_state_canfail ("")) {
849                                         /* failed - don't quit */
850                                         MessageDialog msg (*editor,
851                                                            _("\
852 Ardour was unable to save your session.\n\n\
853 If you still wish to quit, please use the\n\n\
854 \"Just quit\" option."));
855                                         pop_back_splash(msg);
856                                         msg.run ();
857                                         return;
858                                 }
859                                 break;
860                         case 0:
861                                 break;
862                         }
863                 }
864
865                 second_connection.disconnect ();
866                 point_one_second_connection.disconnect ();
867                 point_oh_five_second_connection.disconnect ();
868                 point_zero_one_second_connection.disconnect();
869         }
870
871         /* Save state before deleting the session, as that causes some
872            windows to be destroyed before their visible state can be
873            saved.
874         */
875         save_ardour_state ();
876
877         if (_session) {
878                 // _session->set_deletion_in_progress ();
879                 _session->set_clean ();
880                 _session->remove_pending_capture_state ();
881                 delete _session;
882                 _session = 0;
883         }
884
885         ArdourDialog::close_all_dialogs ();
886         engine->stop (true);
887         quit ();
888 }
889
890 int
891 ARDOUR_UI::ask_about_saving_session (const vector<string>& actions)
892 {
893         ArdourDialog window (_("Unsaved Session"));
894         Gtk::HBox dhbox;  // the hbox for the image and text
895         Gtk::Label  prompt_label;
896         Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING,  Gtk::ICON_SIZE_DIALOG));
897
898         string msg;
899
900         assert (actions.size() >= 3);
901
902         window.add_button (actions[0], RESPONSE_REJECT);
903         window.add_button (actions[1], RESPONSE_APPLY);
904         window.add_button (actions[2], RESPONSE_ACCEPT);
905
906         window.set_default_response (RESPONSE_ACCEPT);
907
908         Gtk::Button noquit_button (msg);
909         noquit_button.set_name ("EditorGTKButton");
910
911         string prompt;
912
913         if (_session->snap_name() == _session->name()) {
914                 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?"),
915                                         _session->snap_name());
916         } else {
917                 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?"),
918                                         _session->snap_name());
919         }
920
921         prompt_label.set_text (prompt);
922         prompt_label.set_name (X_("PrompterLabel"));
923         prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
924
925         dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP);
926         dhbox.set_homogeneous (false);
927         dhbox.pack_start (*dimage, false, false, 5);
928         dhbox.pack_start (prompt_label, true, false, 5);
929         window.get_vbox()->pack_start (dhbox);
930
931         window.set_name (_("Prompter"));
932         window.set_position (Gtk::WIN_POS_MOUSE);
933         window.set_modal (true);
934         window.set_resizable (false);
935
936         dhbox.show();
937         prompt_label.show();
938         dimage->show();
939         window.show();
940         window.set_keep_above (true);
941         window.present ();
942
943         ResponseType r = (ResponseType) window.run();
944
945         window.hide ();
946
947         switch (r) {
948         case RESPONSE_ACCEPT: // save and get out of here
949                 return 1;
950         case RESPONSE_APPLY:  // get out of here
951                 return 0;
952         default:
953                 break;
954         }
955
956         return -1;
957 }
958
959 gint
960 ARDOUR_UI::every_second ()
961 {
962         update_cpu_load ();
963         update_buffer_load ();
964         update_disk_space ();
965         return TRUE;
966 }
967
968 gint
969 ARDOUR_UI::every_point_one_seconds ()
970 {
971         shuttle_box->update_speed_display ();
972         RapidScreenUpdate(); /* EMIT_SIGNAL */
973         return TRUE;
974 }
975
976 gint
977 ARDOUR_UI::every_point_zero_one_seconds ()
978 {
979         // august 2007: actual update frequency: 40Hz, not 100Hz
980
981         SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
982         return TRUE;
983 }
984
985 void
986 ARDOUR_UI::update_sample_rate (framecnt_t)
987 {
988         char buf[64];
989
990         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::update_sample_rate, ignored)
991
992         if (!engine->connected()) {
993
994                 snprintf (buf, sizeof (buf), _("disconnected"));
995
996         } else {
997
998                 framecnt_t rate = engine->frame_rate();
999
1000                 if (fmod (rate, 1000.0) != 0.0) {
1001                         snprintf (buf, sizeof (buf), _("JACK: <span foreground=\"green\">%.1f kHz / %4.1f ms</span>"),
1002                                   (float) rate/1000.0f,
1003                                   (engine->frames_per_cycle() / (float) rate) * 1000.0f);
1004                 } else {
1005                         snprintf (buf, sizeof (buf), _("JACK: <span foreground=\"green\">%" PRId64 " kHz / %4.1f ms</span>"),
1006                                   rate/1000,
1007                                   (engine->frames_per_cycle() / (float) rate) * 1000.0f);
1008                 }
1009         }
1010
1011         sample_rate_label.set_markup (buf);
1012 }
1013
1014 void
1015 ARDOUR_UI::update_format ()
1016 {
1017         if (!_session) {
1018                 format_label.set_text ("");
1019                 return;
1020         }
1021
1022         stringstream s;
1023         s << _("File:") << X_(" <span foreground=\"green\">");
1024
1025         switch (_session->config.get_native_file_header_format ()) {
1026         case BWF:
1027                 s << _("BWF");
1028                 break;
1029         case WAVE:
1030                 s << _("WAV");
1031                 break;
1032         case WAVE64:
1033                 s << _("WAV64");
1034                 break;
1035         case CAF:
1036                 s << _("CAF");
1037                 break;
1038         case AIFF:
1039                 s << _("AIFF");
1040                 break;
1041         case iXML:
1042                 s << _("iXML");
1043                 break;
1044         case RF64:
1045                 s << _("RF64");
1046                 break;
1047         }
1048
1049         s << " ";
1050         
1051         switch (_session->config.get_native_file_data_format ()) {
1052         case FormatFloat:
1053                 s << _("32-float");
1054                 break;
1055         case FormatInt24:
1056                 s << _("24-int");
1057                 break;
1058         case FormatInt16:
1059                 s << _("16-int");
1060                 break;
1061         }
1062
1063         s << X_("</span>");
1064
1065         format_label.set_markup (s.str ());
1066 }
1067
1068 void
1069 ARDOUR_UI::update_cpu_load ()
1070 {
1071         char buf[64];
1072
1073         /* If this text is changed, the set_size_request_to_display_given_text call in ARDOUR_UI::resize_text_widgets
1074            should also be changed.
1075         */
1076
1077         float const c = engine->get_cpu_load ();
1078         snprintf (buf, sizeof (buf), _("DSP: <span foreground=\"%s\">%5.1f%%</span>"), c >= 90 ? X_("red") : X_("green"), c);
1079         cpu_load_label.set_markup (buf);
1080 }
1081
1082 void
1083 ARDOUR_UI::update_buffer_load ()
1084 {
1085         char buf[256];
1086
1087         uint32_t const playback = _session ? _session->playback_load () : 100;
1088         uint32_t const capture = _session ? _session->capture_load () : 100;
1089
1090         /* If this text is changed, the set_size_request_to_display_given_text call in ARDOUR_UI::resize_text_widgets
1091            should also be changed.
1092         */
1093         
1094         if (_session) {
1095                 snprintf (
1096                         buf, sizeof (buf),
1097                         _("Buffers: <span foreground=\"green\">p:</span><span foreground=\"%s\">%" PRIu32 "%%</span> "
1098                                    "<span foreground=\"green\">c:</span><span foreground=\"%s\">%" PRIu32 "%%</span>"),
1099                         playback <= 5 ? X_("red") : X_("green"),
1100                         playback,
1101                         capture <= 5 ? X_("red") : X_("green"),
1102                         capture
1103                         );
1104
1105                 buffer_load_label.set_markup (buf);
1106         } else {
1107                 buffer_load_label.set_text ("");
1108         }
1109 }
1110
1111 void
1112 ARDOUR_UI::count_recenabled_streams (Route& route)
1113 {
1114         Track* track = dynamic_cast<Track*>(&route);
1115         if (track && track->record_enabled()) {
1116                 rec_enabled_streams += track->n_inputs().n_total();
1117         }
1118 }
1119
1120 void
1121 ARDOUR_UI::update_disk_space()
1122 {
1123         if (_session == 0) {
1124                 return;
1125         }
1126
1127         framecnt_t frames = _session->available_capture_duration();
1128         char buf[64];
1129         framecnt_t fr = _session->frame_rate();
1130
1131         if (frames == max_framecnt) {
1132                 snprintf (buf, sizeof (buf), _("Disk: <span foreground=\"green\">24hrs+</span>"));
1133         } else {
1134                 rec_enabled_streams = 0;
1135                 _session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
1136
1137                 if (rec_enabled_streams) {
1138                         frames /= rec_enabled_streams;
1139                 }
1140
1141                 int hrs;
1142                 int mins;
1143                 int secs;
1144
1145                 hrs  = frames / (fr * 3600);
1146
1147                 if (hrs > 24) {
1148                         snprintf (buf, sizeof (buf), _("Disk: <span foreground=\"green\">&gt;24 hrs</span>"));
1149                 } else {
1150                         frames -= hrs * fr * 3600;
1151                         mins = frames / (fr * 60);
1152                         frames -= mins * fr * 60;
1153                         secs = frames / fr;
1154                         
1155                         bool const low = (hrs == 0 && mins <= 30);
1156                         
1157                         snprintf (
1158                                 buf, sizeof(buf),
1159                                 _("Disk: <span foreground=\"%s\">%02dh:%02dm:%02ds</span>"),
1160                                 low ? X_("red") : X_("green"),
1161                                 hrs, mins, secs
1162                                 );
1163                 }
1164         }
1165
1166         disk_space_label.set_markup (buf);
1167
1168         // An attempt to make the disk space label flash red when space has run out.
1169
1170         if (frames < fr * 60 * 5) {
1171         /*      disk_space_box.style ("disk_space_label_empty"); */
1172         } else {
1173         /*      disk_space_box.style ("disk_space_label"); */
1174         }
1175
1176 }
1177
1178 gint
1179 ARDOUR_UI::update_wall_clock ()
1180 {
1181         time_t now;
1182         struct tm *tm_now;
1183         char buf[16];
1184
1185         time (&now);
1186         tm_now = localtime (&now);
1187
1188         sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
1189         wall_clock_label.set_text (buf);
1190
1191         return TRUE;
1192 }
1193
1194 gint
1195 ARDOUR_UI::session_menu (GdkEventButton */*ev*/)
1196 {
1197         session_popup_menu->popup (0, 0);
1198         return TRUE;
1199 }
1200
1201 void
1202 ARDOUR_UI::redisplay_recent_sessions ()
1203 {
1204         std::vector<sys::path> session_directories;
1205         RecentSessionsSorter cmp;
1206
1207         recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
1208         recent_session_model->clear ();
1209
1210         ARDOUR::RecentSessions rs;
1211         ARDOUR::read_recent_sessions (rs);
1212
1213         if (rs.empty()) {
1214                 recent_session_display.set_model (recent_session_model);
1215                 return;
1216         }
1217         //
1218         // sort them alphabetically
1219         sort (rs.begin(), rs.end(), cmp);
1220
1221         for (ARDOUR::RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1222                 session_directories.push_back ((*i).second);
1223         }
1224
1225         for (vector<sys::path>::const_iterator i = session_directories.begin();
1226                         i != session_directories.end(); ++i)
1227         {
1228                 std::vector<sys::path> state_file_paths;
1229
1230                 // now get available states for this session
1231
1232                 get_state_files_in_directory (*i, state_file_paths);
1233
1234                 vector<string*>* states;
1235                 vector<const gchar*> item;
1236                 string fullpath = (*i).to_string();
1237
1238                 /* remove any trailing / */
1239
1240                 if (fullpath[fullpath.length()-1] == '/') {
1241                         fullpath = fullpath.substr (0, fullpath.length()-1);
1242                 }
1243
1244                 /* check whether session still exists */
1245                 if (!Glib::file_test(fullpath.c_str(), Glib::FILE_TEST_EXISTS)) {
1246                         /* session doesn't exist */
1247                         cerr << "skipping non-existent session " << fullpath << endl;
1248                         continue;
1249                 }
1250
1251                 /* now get available states for this session */
1252
1253                 if ((states = Session::possible_states (fullpath)) == 0) {
1254                         /* no state file? */
1255                         continue;
1256                 }
1257
1258                 std::vector<string> state_file_names(get_file_names_no_extension (state_file_paths));
1259
1260                 Gtk::TreeModel::Row row = *(recent_session_model->append());
1261
1262                 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1263                 row[recent_session_columns.fullpath] = fullpath;
1264
1265                 if (state_file_names.size() > 1) {
1266
1267                         // add the children
1268
1269                         for (std::vector<std::string>::iterator i2 = state_file_names.begin();
1270                                         i2 != state_file_names.end(); ++i2)
1271                         {
1272
1273                                 Gtk::TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1274
1275                                 child_row[recent_session_columns.visible_name] = *i2;
1276                                 child_row[recent_session_columns.fullpath] = fullpath;
1277                         }
1278                 }
1279         }
1280
1281         recent_session_display.set_model (recent_session_model);
1282 }
1283
1284 void
1285 ARDOUR_UI::build_session_selector ()
1286 {
1287         session_selector_window = new ArdourDialog (_("Recent Sessions"));
1288
1289         Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1290
1291         session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1292         session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1293         session_selector_window->set_default_response (RESPONSE_ACCEPT);
1294         recent_session_model = TreeStore::create (recent_session_columns);
1295         recent_session_display.set_model (recent_session_model);
1296         recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1297         recent_session_display.set_headers_visible (false);
1298         recent_session_display.get_selection()->set_mode (SELECTION_BROWSE);
1299         recent_session_display.signal_row_activated().connect (sigc::mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1300
1301         scroller->add (recent_session_display);
1302         scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1303
1304         session_selector_window->set_name ("SessionSelectorWindow");
1305         session_selector_window->set_size_request (200, 400);
1306         session_selector_window->get_vbox()->pack_start (*scroller);
1307
1308         recent_session_display.show();
1309         scroller->show();
1310         //session_selector_window->get_vbox()->show();
1311 }
1312
1313 void
1314 ARDOUR_UI::recent_session_row_activated (const TreePath& /*path*/, TreeViewColumn* /*col*/)
1315 {
1316         session_selector_window->response (RESPONSE_ACCEPT);
1317 }
1318
1319 void
1320 ARDOUR_UI::open_recent_session ()
1321 {
1322         bool can_return = (_session != 0);
1323
1324         if (session_selector_window == 0) {
1325                 build_session_selector ();
1326         }
1327
1328         redisplay_recent_sessions ();
1329
1330         while (true) {
1331
1332                 session_selector_window->set_position (WIN_POS_MOUSE);
1333
1334                 ResponseType r = (ResponseType) session_selector_window->run ();
1335
1336                 switch (r) {
1337                 case RESPONSE_ACCEPT:
1338                         break;
1339                 default:
1340                         if (can_return) {
1341                                 session_selector_window->hide();
1342                                 return;
1343                         } else {
1344                                 exit (1);
1345                         }
1346                 }
1347
1348                 if (recent_session_display.get_selection()->count_selected_rows() == 0) {
1349                         continue;
1350                 }
1351
1352                 session_selector_window->hide();
1353
1354                 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1355
1356                 if (i == recent_session_model->children().end()) {
1357                         return;
1358                 }
1359
1360                 std::string path = (*i)[recent_session_columns.fullpath];
1361                 std::string state = (*i)[recent_session_columns.visible_name];
1362
1363                 _session_is_new = false;
1364
1365                 if (load_session (path, state) == 0) {
1366                         break;
1367                 }
1368
1369                 can_return = false;
1370         }
1371 }
1372
1373 bool
1374 ARDOUR_UI::check_audioengine ()
1375 {
1376         if (engine) {
1377                 if (!engine->connected()) {
1378                         MessageDialog msg (string_compose (
1379                                                    _("%1 is not connected to JACK\n"
1380                                                      "You cannot open or close sessions in this condition"),
1381                                                    PROGRAM_NAME));
1382                         pop_back_splash (msg);
1383                         msg.run ();
1384                         return false;
1385                 }
1386                 return true;
1387         } else {
1388                 return false;
1389         }
1390 }
1391
1392 void
1393 ARDOUR_UI::open_session ()
1394 {
1395         if (!check_audioengine()) {
1396                 return;
1397
1398         }
1399
1400         /* popup selector window */
1401
1402         if (open_session_selector == 0) {
1403
1404                 /* ardour sessions are folders */
1405
1406                 open_session_selector = new Gtk::FileChooserDialog (_("Open Session"), FILE_CHOOSER_ACTION_OPEN);
1407                 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1408                 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1409                 open_session_selector->set_default_response(Gtk::RESPONSE_ACCEPT);
1410
1411                 FileFilter session_filter;
1412                 session_filter.add_pattern ("*.ardour");
1413                 session_filter.set_name (string_compose (_("%1 sessions"), PROGRAM_NAME));
1414                 open_session_selector->add_filter (session_filter);
1415                 open_session_selector->set_filter (session_filter);
1416         }
1417
1418         int response = open_session_selector->run();
1419         open_session_selector->hide ();
1420
1421         switch (response) {
1422         case RESPONSE_ACCEPT:
1423                 break;
1424         default:
1425                 open_session_selector->hide();
1426                 return;
1427         }
1428
1429         open_session_selector->hide();
1430         string session_path = open_session_selector->get_filename();
1431         string path, name;
1432         bool isnew;
1433
1434         if (session_path.length() > 0) {
1435                 if (ARDOUR::find_session (session_path, path, name, isnew) == 0) {
1436                         _session_is_new = isnew;
1437                         load_session (path, name);
1438                 }
1439         }
1440 }
1441
1442
1443 void
1444 ARDOUR_UI::session_add_midi_route (bool disk, RouteGroup* route_group, uint32_t how_many, const string& name_template, PluginInfoPtr instrument)
1445 {
1446         list<boost::shared_ptr<MidiTrack> > tracks;
1447
1448         if (_session == 0) {
1449                 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1450                 return;
1451         }
1452
1453         try {
1454                 if (disk) {
1455
1456                         tracks = _session->new_midi_track (instrument, ARDOUR::Normal, route_group, how_many, name_template);
1457
1458                         if (tracks.size() != how_many) {
1459                                 if (how_many == 1) {
1460                                         error << _("could not create a new midi track") << endmsg;
1461                                 } else {
1462                                         error << string_compose (_("could not create %1 new midi tracks"), how_many) << endmsg;
1463                                 }
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 (msg);
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 () && !Config->get_always_play_range()) {
1733                 /* stop playing a range if we currently are */
1734                 _session->request_play_range (0, true);
1735         }
1736
1737         if (Config->get_always_play_range()) {
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 (Config->get_always_play_range ()) {
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 (Config->get_always_play_range()) {
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 (msg);
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 (msg);
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         if (ARDOUR_COMMAND_LINE::no_splash) {
2565                 return;
2566         }
2567
2568         show_splash ();
2569         if (splash) {
2570                 splash->message (msg);
2571                 flush_pending ();
2572         }
2573 }
2574
2575 /** @param quit_on_cancel true if exit() should be called if the user clicks `cancel' in the new session dialog */
2576 int
2577 ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new, string load_template)
2578 {
2579         string session_name;
2580         string session_path;
2581         string template_name;
2582         int ret = -1;
2583         bool likely_new = false;
2584
2585         if (!load_template.empty()) {
2586                 should_be_new = true;
2587                 template_name = load_template;
2588         }
2589
2590         while (ret != 0) {
2591
2592                 if (!should_be_new && !ARDOUR_COMMAND_LINE::session_name.empty()) {
2593
2594                         /* if they named a specific statefile, use it, otherwise they are
2595                            just giving a session folder, and we want to use it as is
2596                            to find the session.
2597                         */
2598
2599                         string::size_type suffix = ARDOUR_COMMAND_LINE::session_name.find (statefile_suffix);
2600
2601                         if (suffix != string::npos) {
2602                                 session_path = Glib::path_get_dirname (ARDOUR_COMMAND_LINE::session_name);
2603                                 session_name = ARDOUR_COMMAND_LINE::session_name.substr (0, suffix);
2604                                 session_name = Glib::path_get_basename (session_name);
2605                         } else {
2606                                 session_path = ARDOUR_COMMAND_LINE::session_name;
2607                                 session_name = Glib::path_get_basename (ARDOUR_COMMAND_LINE::session_name);
2608                         }
2609
2610                 } else {
2611
2612                         bool const apply = run_startup (should_be_new, load_template);
2613
2614                         if (!apply) {
2615                                 if (quit_on_cancel) {
2616                                         exit (1);
2617                                 } else {
2618                                         return ret;
2619                                 }
2620                         }
2621
2622                         /* if we run the startup dialog again, offer more than just "new session" */
2623
2624                         should_be_new = false;
2625
2626                         session_name = _startup->session_name (likely_new);
2627
2628                         string::size_type suffix = session_name.find (statefile_suffix);
2629
2630                         if (suffix != string::npos) {
2631                                 session_name = session_name.substr (0, suffix);
2632                         }
2633
2634                         /* this shouldn't happen, but we catch it just in case it does */
2635
2636                         if (session_name.empty()) {
2637                                 continue;
2638                         }
2639
2640                         if (_startup->use_session_template()) {
2641                                 template_name = _startup->session_template_name();
2642                                 _session_is_new = true;
2643                         }
2644
2645                         if (session_name[0] == G_DIR_SEPARATOR ||
2646                             (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == G_DIR_SEPARATOR) ||
2647                             (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == G_DIR_SEPARATOR)) {
2648
2649                                 /* absolute path or cwd-relative path specified for session name: infer session folder
2650                                    from what was given.
2651                                 */
2652
2653                                 session_path = Glib::path_get_dirname (session_name);
2654                                 session_name = Glib::path_get_basename (session_name);
2655
2656                         } else {
2657
2658                                 session_path = _startup->session_folder();
2659
2660                                 char illegal = Session::session_name_is_legal (session_name);
2661
2662                                 if (illegal) {
2663                                         MessageDialog msg (*_startup,
2664                                                            string_compose (_("To ensure compatibility with various systems\n"
2665                                                                              "session names may not contain a '%1' character"),
2666                                                                            illegal));
2667                                         msg.run ();
2668                                         ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2669                                         continue;
2670                                 }
2671                         }
2672                 }
2673
2674                 if (create_engine ()) {
2675                         break;
2676                 }
2677
2678                 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2679
2680                         if (likely_new) {
2681
2682                                 std::string existing = Glib::build_filename (session_path, session_name);
2683
2684                                 if (!ask_about_loading_existing_session (existing)) {
2685                                         ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2686                                         continue;
2687                                 }
2688                         }
2689
2690                         _session_is_new = false;
2691
2692                 } else {
2693
2694                         if (!likely_new) {
2695                                 MessageDialog msg (string_compose (_("There is no existing session at \"%1\""), session_path));
2696                                 msg.run ();
2697                                 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2698                                 continue;
2699                         }
2700
2701                         if (session_name.find ('/') != std::string::npos) {
2702                                 MessageDialog msg (*_startup,
2703                                                    _("To ensure compatibility with various systems\n"
2704                                                      "session names may not contain a '/' character"));
2705                                 msg.run ();
2706                                 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2707                                 continue;
2708                         }
2709
2710                         if (session_name.find ('\\') != std::string::npos) {
2711                                 MessageDialog msg (*_startup,
2712                                                    _("To ensure compatibility with various systems\n"
2713                                                      "session names may not contain a '\\' character"));
2714                                 msg.run ();
2715                                 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2716                                 continue;
2717                         }
2718
2719                         _session_is_new = true;
2720                 }
2721
2722                 if (likely_new && template_name.empty()) {
2723
2724                         ret = build_session_from_nsd (session_path, session_name);
2725
2726                 } else {
2727
2728                         ret = load_session (session_path, session_name, template_name);
2729
2730                         if (ret == -2) {
2731                                 /* not connected to the AudioEngine, so quit to avoid an infinite loop */
2732                                 exit (1);
2733                         }
2734
2735                         if (!ARDOUR_COMMAND_LINE::immediate_save.empty()) {
2736                                 _session->save_state (ARDOUR_COMMAND_LINE::immediate_save, false);
2737                                 exit (1);
2738                         }
2739                 }
2740         }
2741
2742         return ret;
2743 }
2744
2745 void
2746 ARDOUR_UI::close_session()
2747 {
2748         if (!check_audioengine()) {
2749                 return;
2750         }
2751
2752         if (unload_session (true)) {
2753                 return;
2754         }
2755
2756         ARDOUR_COMMAND_LINE::session_name = "";
2757
2758         if (get_session_parameters (true, false)) {
2759                 exit (1);
2760         }
2761
2762         goto_editor_window ();
2763 }
2764
2765 /** @param snap_name Snapshot name (without .ardour suffix).
2766  *  @return -2 if the load failed because we are not connected to the AudioEngine.
2767  */
2768 int
2769 ARDOUR_UI::load_session (const std::string& path, const std::string& snap_name, std::string mix_template)
2770 {
2771         Session *new_session;
2772         int unload_status;
2773         int retval = -1;
2774
2775         session_loaded = false;
2776
2777         if (!check_audioengine()) {
2778                 return -2;
2779         }
2780
2781         unload_status = unload_session ();
2782
2783         if (unload_status < 0) {
2784                 goto out;
2785         } else if (unload_status > 0) {
2786                 retval = 0;
2787                 goto out;
2788         }
2789
2790         loading_message (string_compose (_("Please wait while %1 loads your session"), PROGRAM_NAME));
2791
2792         try {
2793                 new_session = new Session (*engine, path, snap_name, 0, mix_template);
2794         }
2795
2796         /* this one is special */
2797
2798         catch (AudioEngine::PortRegistrationFailure& err) {
2799
2800                 MessageDialog msg (err.what(),
2801                                    true,
2802                                    Gtk::MESSAGE_INFO,
2803                                    Gtk::BUTTONS_CLOSE);
2804
2805                 msg.set_title (_("Port Registration Error"));
2806                 msg.set_secondary_text (_("Click the Close button to try again."));
2807                 msg.set_position (Gtk::WIN_POS_CENTER);
2808                 pop_back_splash (msg);
2809                 msg.present ();
2810
2811                 int response = msg.run ();
2812
2813                 msg.hide ();
2814
2815                 switch (response) {
2816                 case RESPONSE_CANCEL:
2817                         exit (1);
2818                 default:
2819                         break;
2820                 }
2821                 goto out;
2822         }
2823
2824         catch (...) {
2825
2826                 MessageDialog msg (string_compose(
2827                                            _("Session \"%1 (snapshot %2)\" did not load successfully"),
2828                                            path, snap_name),
2829                                    true,
2830                                    Gtk::MESSAGE_INFO,
2831                                    BUTTONS_OK);
2832
2833                 msg.set_title (_("Loading Error"));
2834                 msg.set_secondary_text (_("Click the Refresh button to try again."));
2835                 msg.add_button (Stock::REFRESH, 1);
2836                 msg.set_position (Gtk::WIN_POS_CENTER);
2837                 pop_back_splash (msg);
2838                 msg.present ();
2839
2840                 int response = msg.run ();
2841
2842                 switch (response) {
2843                 case 1:
2844                         break;
2845                 default:
2846                         exit (1);
2847                 }
2848
2849                 msg.hide ();
2850
2851                 goto out;
2852         }
2853
2854         {
2855                 list<string> const u = new_session->unknown_processors ();
2856                 if (!u.empty()) {
2857                         MissingPluginDialog d (_session, u);
2858                         d.run ();
2859                 }
2860         }
2861
2862         /* Now the session been created, add the transport controls */
2863         new_session->add_controllable(roll_controllable);
2864         new_session->add_controllable(stop_controllable);
2865         new_session->add_controllable(goto_start_controllable);
2866         new_session->add_controllable(goto_end_controllable);
2867         new_session->add_controllable(auto_loop_controllable);
2868         new_session->add_controllable(play_selection_controllable);
2869         new_session->add_controllable(rec_controllable);
2870
2871         set_session (new_session);
2872
2873         session_loaded = true;
2874
2875         goto_editor_window ();
2876
2877         if (_session) {
2878                 _session->set_clean ();
2879         }
2880
2881         flush_pending ();
2882         retval = 0;
2883
2884   out:
2885         return retval;
2886 }
2887
2888 int
2889 ARDOUR_UI::build_session (const std::string& path, const std::string& snap_name, BusProfile& bus_profile)
2890 {
2891         Session *new_session;
2892         int x;
2893
2894         if (!check_audioengine()) {
2895                 return -1;
2896         }
2897
2898         session_loaded = false;
2899
2900         x = unload_session ();
2901
2902         if (x < 0) {
2903                 return -1;
2904         } else if (x > 0) {
2905                 return 0;
2906         }
2907
2908         _session_is_new = true;
2909
2910         try {
2911                 new_session = new Session (*engine, path, snap_name, &bus_profile);
2912         }
2913
2914         catch (...) {
2915
2916                 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2917                 pop_back_splash (msg);
2918                 msg.run ();
2919                 return -1;
2920         }
2921
2922         /* Give the new session the default GUI state, if such things exist */
2923
2924         XMLNode* n;
2925         n = Config->instant_xml (X_("Editor"));
2926         if (n) {
2927                 new_session->add_instant_xml (*n, false);
2928         }
2929         n = Config->instant_xml (X_("Mixer"));
2930         if (n) {
2931                 new_session->add_instant_xml (*n, false);
2932         }
2933
2934         /* Put the playhead at 0 and scroll fully left */
2935         n = new_session->instant_xml (X_("Editor"));
2936         if (n) {
2937                 n->add_property (X_("playhead"), X_("0"));
2938                 n->add_property (X_("left-frame"), X_("0"));
2939         }
2940
2941         set_session (new_session);
2942
2943         session_loaded = true;
2944
2945         new_session->save_state(new_session->name());
2946
2947         return 0;
2948 }
2949
2950 void
2951 ARDOUR_UI::launch_chat ()
2952 {
2953 #ifdef __APPLE__
2954         open_uri("http://webchat.freenode.net/?channels=ardour-osx");
2955 #else
2956         open_uri("http://webchat.freenode.net/?channels=ardour");
2957 #endif
2958 }
2959
2960 void
2961 ARDOUR_UI::show_about ()
2962 {
2963         if (about == 0) {
2964                 about = new About;
2965                 about->signal_response().connect(sigc::mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2966         }
2967
2968         about->set_transient_for(*editor);
2969         about->show_all ();
2970 }
2971
2972 void
2973 ARDOUR_UI::launch_manual ()
2974 {
2975         PBD::open_uri("http://ardour.org/flossmanual");
2976 }
2977
2978 void
2979 ARDOUR_UI::launch_reference ()
2980 {
2981         PBD::open_uri("http://ardour.org/refmanual");
2982 }
2983
2984 void
2985 ARDOUR_UI::hide_about ()
2986 {
2987         if (about) {
2988                 about->get_window()->set_cursor ();
2989                 about->hide ();
2990         }
2991 }
2992
2993 void
2994 ARDOUR_UI::about_signal_response (int /*response*/)
2995 {
2996         hide_about();
2997 }
2998
2999 void
3000 ARDOUR_UI::show_splash ()
3001 {
3002         if (splash == 0) {
3003                 try {
3004                         splash = new Splash;
3005                 } catch (...) {
3006                         cerr << "Splash could not be created\n";
3007                         return;
3008                 }
3009         }
3010
3011         splash->present ();
3012         splash->pop_front ();
3013         splash->queue_draw ();
3014         splash->get_window()->process_updates (true);
3015         flush_pending ();
3016 }
3017
3018 void
3019 ARDOUR_UI::hide_splash ()
3020 {
3021         if (splash) {
3022                 splash->hide();
3023         }
3024 }
3025
3026 void
3027 ARDOUR_UI::display_cleanup_results (ARDOUR::CleanupReport& rep, const gchar* list_title,
3028                                     const string& plural_msg, const string& singular_msg)
3029 {
3030         size_t removed;
3031
3032         removed = rep.paths.size();
3033
3034         if (removed == 0) {
3035                 MessageDialog msgd (*editor,
3036                                     _("No files were ready for clean-up"),
3037                                     true,
3038                                     Gtk::MESSAGE_INFO,
3039                                     Gtk::BUTTONS_OK);
3040                 msgd.set_title (_("Clean-up"));
3041                 msgd.set_secondary_text (_("If this seems suprising, \n\
3042 check for any existing snapshots.\n\
3043 These may still include regions that\n\
3044 require some unused files to continue to exist."));
3045
3046                 msgd.run ();
3047                 return;
3048         }
3049
3050         ArdourDialog results (_("Clean-up"), true, false);
3051
3052         struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
3053             CleanupResultsModelColumns() {
3054                     add (visible_name);
3055                     add (fullpath);
3056             }
3057             Gtk::TreeModelColumn<std::string> visible_name;
3058             Gtk::TreeModelColumn<std::string> fullpath;
3059         };
3060
3061
3062         CleanupResultsModelColumns results_columns;
3063         Glib::RefPtr<Gtk::ListStore> results_model;
3064         Gtk::TreeView results_display;
3065
3066         results_model = ListStore::create (results_columns);
3067         results_display.set_model (results_model);
3068         results_display.append_column (list_title, results_columns.visible_name);
3069
3070         results_display.set_name ("CleanupResultsList");
3071         results_display.set_headers_visible (true);
3072         results_display.set_headers_clickable (false);
3073         results_display.set_reorderable (false);
3074
3075         Gtk::ScrolledWindow list_scroller;
3076         Gtk::Label txt;
3077         Gtk::VBox dvbox;
3078         Gtk::HBox dhbox;  // the hbox for the image and text
3079         Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
3080         Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO,  Gtk::ICON_SIZE_DIALOG));
3081
3082         dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
3083
3084         const string dead_directory = _session->session_directory().dead_path().to_string();
3085
3086         /* subst:
3087            %1 - number of files removed
3088            %2 - location of "dead"
3089            %3 - size of files affected
3090            %4 - prefix for "bytes" to produce sensible results (e.g. mega, kilo, giga)
3091         */
3092
3093         const char* bprefix;
3094         double space_adjusted = 0;
3095
3096         if (rep.space < 1000) {
3097                 bprefix = X_("");
3098                 space_adjusted = rep.space;
3099         } else if (rep.space < 1000000) {
3100                 bprefix = X_("kilo");
3101                 space_adjusted = truncf((float)rep.space / 1000.0);
3102         } else if (rep.space < 1000000 * 1000) {
3103                 bprefix = X_("mega");
3104                 space_adjusted = truncf((float)rep.space / (1000.0 * 1000.0));
3105         } else {
3106                 bprefix = X_("giga");
3107                 space_adjusted = truncf((float)rep.space / (1000.0 * 1000 * 1000.0));
3108         }
3109
3110         if (removed > 1) {
3111                 txt.set_text (string_compose (plural_msg, removed, dead_directory, space_adjusted, bprefix));
3112         } else {
3113                 txt.set_text (string_compose (singular_msg, removed, dead_directory, space_adjusted, bprefix));
3114         }
3115
3116         dhbox.pack_start (*dimage, true, false, 5);
3117         dhbox.pack_start (txt, true, false, 5);
3118
3119         for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
3120                 TreeModel::Row row = *(results_model->append());
3121                 row[results_columns.visible_name] = *i;
3122                 row[results_columns.fullpath] = *i;
3123         }
3124
3125         list_scroller.add (results_display);
3126         list_scroller.set_size_request (-1, 150);
3127         list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
3128
3129         dvbox.pack_start (dhbox, true, false, 5);
3130         dvbox.pack_start (list_scroller, true, false, 5);
3131         ddhbox.pack_start (dvbox, true, false, 5);
3132
3133         results.get_vbox()->pack_start (ddhbox, true, false, 5);
3134         results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
3135         results.set_default_response (RESPONSE_CLOSE);
3136         results.set_position (Gtk::WIN_POS_MOUSE);
3137
3138         results_display.show();
3139         list_scroller.show();
3140         txt.show();
3141         dvbox.show();
3142         dhbox.show();
3143         ddhbox.show();
3144         dimage->show();
3145
3146         //results.get_vbox()->show();
3147         results.set_resizable (false);
3148
3149         results.run ();
3150
3151 }
3152
3153 void
3154 ARDOUR_UI::cleanup ()
3155 {
3156         if (_session == 0) {
3157                 /* shouldn't happen: menu item is insensitive */
3158                 return;
3159         }
3160
3161
3162         MessageDialog checker (_("Are you sure you want to clean-up?"),
3163                                 true,
3164                                 Gtk::MESSAGE_QUESTION,
3165                                 Gtk::BUTTONS_NONE);
3166
3167         checker.set_title (_("Clean-up"));
3168
3169         checker.set_secondary_text(_("Clean-up is a destructive operation.\n\
3170 ALL undo/redo information will be lost if you clean-up.\n\
3171 Clean-up will move all unused files to a \"dead\" location."));
3172
3173         checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
3174         checker.add_button (_("Clean-up"), RESPONSE_ACCEPT);
3175         checker.set_default_response (RESPONSE_CANCEL);
3176
3177         checker.set_name (_("CleanupDialog"));
3178         checker.set_wmclass (X_("ardour_cleanup"), PROGRAM_NAME);
3179         checker.set_position (Gtk::WIN_POS_MOUSE);
3180
3181         switch (checker.run()) {
3182         case RESPONSE_ACCEPT:
3183                 break;
3184         default:
3185                 return;
3186         }
3187
3188         ARDOUR::CleanupReport rep;
3189
3190         editor->prepare_for_cleanup ();
3191
3192         /* do not allow flush until a session is reloaded */
3193
3194         Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
3195         if (act) {
3196                 act->set_sensitive (false);
3197         }
3198
3199         if (_session->cleanup_sources (rep)) {
3200                 editor->finish_cleanup ();
3201                 return;
3202         }
3203
3204         editor->finish_cleanup ();
3205
3206         checker.hide();
3207         display_cleanup_results (rep,
3208                                  _("Cleaned Files"),
3209                                  _("\
3210 The following %1 files were not in use and \n\
3211 have been moved to:\n\n\
3212 %2\n\n\
3213 After a restart of Ardour,\n\n\
3214 Session -> Clean-up -> Flush Wastebasket\n\n\
3215 will release an additional\n\
3216 %3 %4bytes of disk space.\n"),
3217                                  _("\
3218 The following file was not in use and \n\
3219 has been moved to:\n                            \
3220 %2\n\n\
3221 After a restart of Ardour,\n\n\
3222 Session -> Clean-up -> Flush Wastebasket\n\n\
3223 will release an additional\n\
3224 %3 %4bytes of disk space.\n"
3225                                          ));
3226
3227 }
3228
3229 void
3230 ARDOUR_UI::flush_trash ()
3231 {
3232         if (_session == 0) {
3233                 /* shouldn't happen: menu item is insensitive */
3234                 return;
3235         }
3236
3237         ARDOUR::CleanupReport rep;
3238
3239         if (_session->cleanup_trash_sources (rep)) {
3240                 return;
3241         }
3242
3243         display_cleanup_results (rep,
3244                                  _("deleted file"),
3245                                  _("The following %1 files were deleted from\n\
3246 %2,\n\
3247 releasing %3 %4bytes of disk space"),
3248                                  _("The following file was deleted from\n\
3249 %2,\n\
3250 releasing %3 %4bytes of disk space"));
3251 }
3252
3253 void
3254 ARDOUR_UI::add_route (Gtk::Window* float_window)
3255 {
3256         int count;
3257
3258         if (!_session) {
3259                 return;
3260         }
3261
3262         if (add_route_dialog == 0) {
3263                 add_route_dialog = new AddRouteDialog (_session);
3264                 add_route_dialog->set_position (WIN_POS_MOUSE);
3265                 if (float_window) {
3266                         add_route_dialog->set_transient_for (*float_window);
3267                 }
3268         }
3269
3270         if (add_route_dialog->is_visible()) {
3271                 /* we're already doing this */
3272                 return;
3273         }
3274
3275         ResponseType r = (ResponseType) add_route_dialog->run ();
3276
3277         add_route_dialog->hide();
3278
3279         switch (r) {
3280                 case RESPONSE_ACCEPT:
3281                         break;
3282                 default:
3283                         return;
3284                         break;
3285         }
3286
3287         if ((count = add_route_dialog->count()) <= 0) {
3288                 return;
3289         }
3290
3291         string template_path = add_route_dialog->track_template();
3292
3293         if (!template_path.empty()) {
3294                 _session->new_route_from_template (count, template_path);
3295                 return;
3296         }
3297
3298         uint32_t input_chan = add_route_dialog->channels ();
3299         uint32_t output_chan;
3300         string name_template = add_route_dialog->name_template ();
3301         PluginInfoPtr instrument = add_route_dialog->requested_instrument ();
3302         RouteGroup* route_group = add_route_dialog->route_group ();
3303
3304         AutoConnectOption oac = Config->get_output_auto_connect();
3305
3306         if (oac & AutoConnectMaster) {
3307                 output_chan = (_session->master_out() ? _session->master_out()->n_inputs().n_audio() : input_chan);
3308         } else {
3309                 output_chan = input_chan;
3310         }
3311
3312         /* XXX do something with name template */
3313
3314         if (add_route_dialog->midi_tracks_wanted()) {
3315                 session_add_midi_track (route_group, count, name_template, instrument);
3316         } else if (add_route_dialog->audio_tracks_wanted()) {
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 XMLNode*
3324 ARDOUR_UI::mixer_settings () const
3325 {
3326         XMLNode* node = 0;
3327
3328         if (_session) {
3329                 node = _session->instant_xml(X_("Mixer"));
3330         } else {
3331                 node = Config->instant_xml(X_("Mixer"));
3332         }
3333
3334         if (!node) {
3335                 node = new XMLNode (X_("Mixer"));
3336         }
3337
3338         return node;
3339 }
3340
3341 XMLNode*
3342 ARDOUR_UI::editor_settings () const
3343 {
3344         XMLNode* node = 0;
3345
3346         if (_session) {
3347                 node = _session->instant_xml(X_("Editor"));
3348         } else {
3349                 node = Config->instant_xml(X_("Editor"));
3350         }
3351
3352         if (!node) {
3353                 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
3354                         node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
3355                 }
3356         }
3357
3358         if (!node) {
3359                 node = new XMLNode (X_("Editor"));
3360         }
3361
3362         return node;
3363 }
3364
3365 XMLNode*
3366 ARDOUR_UI::keyboard_settings () const
3367 {
3368         XMLNode* node = 0;
3369
3370         node = Config->extra_xml(X_("Keyboard"));
3371
3372         if (!node) {
3373                 node = new XMLNode (X_("Keyboard"));
3374         }
3375
3376         return node;
3377 }
3378
3379 void
3380 ARDOUR_UI::create_xrun_marker (framepos_t where)
3381 {
3382         editor->mouse_add_new_marker (where, false, true);
3383 }
3384
3385 void
3386 ARDOUR_UI::halt_on_xrun_message ()
3387 {
3388         MessageDialog msg (*editor,
3389                            _("Recording was stopped because your system could not keep up."));
3390         msg.run ();
3391 }
3392
3393 void
3394 ARDOUR_UI::xrun_handler (framepos_t where)
3395 {
3396         if (!_session) {
3397                 return;
3398         }
3399
3400         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::xrun_handler, where)
3401
3402         if (_session && Config->get_create_xrun_marker() && _session->actively_recording()) {
3403                 create_xrun_marker(where);
3404         }
3405
3406         if (_session && Config->get_stop_recording_on_xrun() && _session->actively_recording()) {
3407                 halt_on_xrun_message ();
3408         }
3409 }
3410
3411 void
3412 ARDOUR_UI::disk_overrun_handler ()
3413 {
3414         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::disk_overrun_handler)
3415
3416         if (!have_disk_speed_dialog_displayed) {
3417                 have_disk_speed_dialog_displayed = true;
3418                 MessageDialog* msg = new MessageDialog (*editor, string_compose (_("\
3419 The disk system on your computer\n\
3420 was not able to keep up with %1.\n\
3421 \n\
3422 Specifically, it failed to write data to disk\n\
3423 quickly enough to keep up with recording.\n"), PROGRAM_NAME));
3424                 msg->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3425                 msg->show ();
3426         }
3427 }
3428
3429 void
3430 ARDOUR_UI::disk_underrun_handler ()
3431 {
3432         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::disk_underrun_handler)
3433
3434         if (!have_disk_speed_dialog_displayed) {
3435                 have_disk_speed_dialog_displayed = true;
3436                 MessageDialog* msg = new MessageDialog (
3437                         *editor, string_compose (_("The disk system on your computer\n\
3438 was not able to keep up with %1.\n\
3439 \n\
3440 Specifically, it failed to read data from disk\n\
3441 quickly enough to keep up with playback.\n"), PROGRAM_NAME));
3442                 msg->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3443                 msg->show ();
3444         }
3445 }
3446
3447 void
3448 ARDOUR_UI::disk_speed_dialog_gone (int /*ignored_response*/, MessageDialog* msg)
3449 {
3450         have_disk_speed_dialog_displayed = false;
3451         delete msg;
3452 }
3453
3454 void
3455 ARDOUR_UI::session_dialog (std::string msg)
3456 {
3457         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::session_dialog, msg)
3458
3459         MessageDialog* d;
3460
3461         if (editor) {
3462                 d = new MessageDialog (*editor, msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3463         } else {
3464                 d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3465         }
3466
3467         d->show_all ();
3468         d->run ();
3469         delete d;
3470 }
3471
3472 int
3473 ARDOUR_UI::pending_state_dialog ()
3474 {
3475         HBox* hbox = new HBox();
3476         Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3477         ArdourDialog dialog (_("Crash Recovery"), true);
3478         Label  message (_("\
3479 This session appears to have been in\n\
3480 middle of recording when ardour or\n\
3481 the computer was shutdown.\n\
3482 \n\
3483 Ardour can recover any captured audio for\n\
3484 you, or it can ignore it. Please decide\n\
3485 what you would like to do.\n"));
3486         image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3487         hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3488         hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3489         dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3490         dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3491         dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3492         dialog.set_default_response (RESPONSE_ACCEPT);
3493         dialog.set_position (WIN_POS_CENTER);
3494         message.show();
3495         image->show();
3496         hbox->show();
3497
3498         switch (dialog.run ()) {
3499         case RESPONSE_ACCEPT:
3500                 return 1;
3501         default:
3502                 return 0;
3503         }
3504 }
3505
3506 int
3507 ARDOUR_UI::sr_mismatch_dialog (framecnt_t desired, framecnt_t actual)
3508 {
3509         HBox* hbox = new HBox();
3510         Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3511         ArdourDialog dialog (_("Sample Rate Mismatch"), true);
3512         Label  message (string_compose (_("\
3513 This session was created with a sample rate of %1 Hz\n\
3514 \n\
3515 The audioengine is currently running at %2 Hz\n"), desired, actual));
3516
3517         image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3518         hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3519         hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3520         dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3521         dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
3522         dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
3523         dialog.set_default_response (RESPONSE_ACCEPT);
3524         dialog.set_position (WIN_POS_CENTER);
3525         message.show();
3526         image->show();
3527         hbox->show();
3528
3529         switch (dialog.run ()) {
3530         case RESPONSE_ACCEPT:
3531                 return 0;
3532         default:
3533                 return 1;
3534         }
3535 }
3536
3537
3538 void
3539 ARDOUR_UI::disconnect_from_jack ()
3540 {
3541         if (engine) {
3542                 if( engine->disconnect_from_jack ()) {
3543                         MessageDialog msg (*editor, _("Could not disconnect from JACK"));
3544                         msg.run ();
3545                 }
3546
3547                 update_sample_rate (0);
3548         }
3549 }
3550
3551 void
3552 ARDOUR_UI::reconnect_to_jack ()
3553 {
3554         if (engine) {
3555                 if (engine->reconnect_to_jack ()) {
3556                         MessageDialog msg (*editor,  _("Could not reconnect to JACK"));
3557                         msg.run ();
3558                 }
3559
3560                 update_sample_rate (0);
3561         }
3562 }
3563
3564 void
3565 ARDOUR_UI::use_config ()
3566 {
3567         XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3568         if (node) {
3569                 set_transport_controllable_state (*node);
3570         }
3571 }
3572
3573 void
3574 ARDOUR_UI::update_transport_clocks (framepos_t pos)
3575 {
3576         if (Config->get_primary_clock_delta_edit_cursor()) {
3577                 primary_clock->set (pos, false, editor->get_preferred_edit_position());
3578         } else {
3579                 primary_clock->set (pos);
3580         }
3581
3582         if (Config->get_secondary_clock_delta_edit_cursor()) {
3583                 secondary_clock->set (pos, false, editor->get_preferred_edit_position());
3584         } else {
3585                 secondary_clock->set (pos);
3586         }
3587
3588         if (big_clock_window->get()) {
3589                 big_clock->set (pos);
3590         }
3591 }
3592
3593
3594 void
3595 ARDOUR_UI::step_edit_status_change (bool yn)
3596 {
3597         // XXX should really store pre-step edit status of things
3598         // we make insensitive
3599
3600         if (yn) {
3601                 rec_button.set_active_state (Mid);
3602                 rec_button.set_sensitive (false);
3603         } else {
3604                 rec_button.unset_active_state ();;
3605                 rec_button.set_sensitive (true);
3606         }
3607 }
3608
3609 void
3610 ARDOUR_UI::record_state_changed ()
3611 {
3612         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::record_state_changed);
3613
3614         if (!_session || !big_clock_window->get()) {
3615                 /* why bother - the clock isn't visible */
3616                 return;
3617         }
3618
3619         if (_session->record_status () == Session::Recording && _session->have_rec_enabled_track ()) {
3620                 big_clock->set_active (true);
3621         } else {
3622                 big_clock->set_active (false);
3623         }
3624 }
3625
3626 bool
3627 ARDOUR_UI::first_idle ()
3628 {
3629         if (_session) {
3630                 _session->allow_auto_play (true);
3631         }
3632
3633         if (editor) {
3634                 editor->first_idle();
3635         }
3636
3637         Keyboard::set_can_save_keybindings (true);
3638         return false;
3639 }
3640
3641 void
3642 ARDOUR_UI::store_clock_modes ()
3643 {
3644         XMLNode* node = new XMLNode(X_("ClockModes"));
3645
3646         for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3647                 XMLNode* child = new XMLNode (X_("Clock"));
3648                 
3649                 child->add_property (X_("name"), (*x)->name());
3650                 child->add_property (X_("mode"), enum_2_string ((*x)->mode()));
3651                 child->add_property (X_("on"), ((*x)->off() ? X_("no") : X_("yes")));
3652
3653                 node->add_child_nocopy (*child);
3654         }
3655
3656         _session->add_extra_xml (*node);
3657         _session->set_dirty ();
3658 }
3659
3660 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3661         : Controllable (name), ui (u), type(tp)
3662 {
3663
3664 }
3665
3666 void
3667 ARDOUR_UI::TransportControllable::set_value (double val)
3668 {
3669         if (val < 0.5) {
3670                 /* do nothing: these are radio-style actions */
3671                 return;
3672         }
3673
3674         const char *action = 0;
3675
3676         switch (type) {
3677         case Roll:
3678                 action = X_("Roll");
3679                 break;
3680         case Stop:
3681                 action = X_("Stop");
3682                 break;
3683         case GotoStart:
3684                 action = X_("Goto Start");
3685                 break;
3686         case GotoEnd:
3687                 action = X_("Goto End");
3688                 break;
3689         case AutoLoop:
3690                 action = X_("Loop");
3691                 break;
3692         case PlaySelection:
3693                 action = X_("Play Selection");
3694                 break;
3695         case RecordEnable:
3696                 action = X_("Record");
3697                 break;
3698         default:
3699                 break;
3700         }
3701
3702         if (action == 0) {
3703                 return;
3704         }
3705
3706         Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3707
3708         if (act) {
3709                 act->activate ();
3710         }
3711 }
3712
3713 double
3714 ARDOUR_UI::TransportControllable::get_value (void) const
3715 {
3716         float val = 0.0;
3717
3718         switch (type) {
3719         case Roll:
3720                 break;
3721         case Stop:
3722                 break;
3723         case GotoStart:
3724                 break;
3725         case GotoEnd:
3726                 break;
3727         case AutoLoop:
3728                 break;
3729         case PlaySelection:
3730                 break;
3731         case RecordEnable:
3732                 break;
3733         default:
3734                 break;
3735         }
3736
3737         return val;
3738 }
3739
3740 void
3741 ARDOUR_UI::setup_profile ()
3742 {
3743         if (gdk_screen_width() < 1200) {
3744                 Profile->set_small_screen ();
3745         }
3746
3747
3748         if (getenv ("ARDOUR_SAE")) {
3749                 Profile->set_sae ();
3750                 Profile->set_single_package ();
3751         }
3752 }
3753
3754 void
3755 ARDOUR_UI::toggle_translations ()
3756 {
3757         using namespace Glib;
3758
3759         RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("EnableTranslation"));
3760         if (act) {
3761                 RefPtr<ToggleAction> ract = RefPtr<ToggleAction>::cast_dynamic (act);
3762                 if (ract) {
3763
3764                         string i18n_killer = ARDOUR::translation_kill_path();
3765
3766                         bool already_enabled = !ARDOUR::translations_are_disabled ();
3767
3768                         if (ract->get_active ()) {
3769 /* we don't care about errors */
3770                                 int fd = ::open (i18n_killer.c_str(), O_RDONLY|O_CREAT, 0644);
3771                                 close (fd);
3772                         } else {
3773 /* we don't care about errors */
3774                                 unlink (i18n_killer.c_str());
3775                         }
3776
3777                         if (already_enabled != ract->get_active()) {
3778                                 MessageDialog win (already_enabled ? _("Translations disabled") : _("Translations enabled"),
3779                                                    false,
3780                                                    Gtk::MESSAGE_WARNING,
3781                                                    Gtk::BUTTONS_OK);
3782                                 win.set_secondary_text (string_compose (_("You must restart %1 for this to take effect."), PROGRAM_NAME));
3783                                 win.set_position (Gtk::WIN_POS_CENTER);
3784                                 win.present ();
3785                                 win.run ();
3786                         }
3787                 }
3788         }
3789 }
3790
3791 /** Add a window proxy to our list, so that its state will be saved.
3792  *  This call also causes the window to be created and opened if its
3793  *  state was saved as `visible'.
3794  */
3795 void
3796 ARDOUR_UI::add_window_proxy (WindowProxyBase* p)
3797 {
3798         _window_proxies.push_back (p);
3799         p->maybe_show ();
3800 }
3801
3802 /** Remove a window proxy from our list.  Must be called if a WindowProxy
3803  *  is deleted, to prevent hanging pointers.
3804  */
3805 void
3806 ARDOUR_UI::remove_window_proxy (WindowProxyBase* p)
3807 {
3808         _window_proxies.remove (p);
3809 }
3810
3811 int
3812 ARDOUR_UI::missing_file (Session*s, std::string str, DataType type)
3813 {
3814         MissingFileDialog dialog (s, str, type);
3815
3816         dialog.show ();
3817         dialog.present ();
3818
3819         int result = dialog.run ();
3820         dialog.hide ();
3821
3822         switch (result) {
3823         case RESPONSE_OK:
3824                 break;
3825         default:
3826                 return 1; // quit entire session load
3827         }
3828
3829         result = dialog.get_action ();
3830
3831         return result;
3832 }
3833
3834 int
3835 ARDOUR_UI::ambiguous_file (std::string file, std::string /*path*/, std::vector<std::string> hits)
3836 {
3837         AmbiguousFileDialog dialog (file, hits);
3838
3839         dialog.show ();
3840         dialog.present ();
3841
3842         dialog.run ();
3843         return dialog.get_which ();
3844 }
3845
3846 /** Allocate our thread-local buffers */
3847 void
3848 ARDOUR_UI::get_process_buffers ()
3849 {
3850         _process_thread->get_buffers ();
3851 }
3852
3853 /** Drop our thread-local buffers */
3854 void
3855 ARDOUR_UI::drop_process_buffers ()
3856 {
3857         _process_thread->drop_buffers ();
3858 }
3859
3860 void
3861 ARDOUR_UI::feedback_detected ()
3862 {
3863         _feedback_exists = true;
3864 }
3865
3866 void
3867 ARDOUR_UI::successful_graph_sort ()
3868 {
3869         _feedback_exists = false;
3870 }
3871
3872 void
3873 ARDOUR_UI::midi_panic ()
3874 {
3875         if (_session) {
3876                 _session->midi_panic();
3877         }
3878 }