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