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